Regex 使用正则表达式从CSV提取数据并将其转换为JSON

Regex 使用正则表达式从CSV提取数据并将其转换为JSON,regex,json,qt,csv,Regex,Json,Qt,Csv,假设您在CSV文件中有一个具有这种布局的表: name,property1 [unit1],property2 [unit2] name1,4.5,2.3 name2,3.2,7.4 name3,5.5,6.1 最重要的是,我必须解释我使用的是Qt4.7,无法更新;此外,我无法安装Qxt,因此我依赖于JSON解析/编码。此外,CSV文件不是由我创建/维护的,因此我也不能真正更改它 有了这些,我意识到我需要一些东西,所以这是一个多重问题: 我应该如何编写正则表达式来读取每列标题中的单位?请注意,

假设您在CSV文件中有一个具有这种布局的表:

name,property1 [unit1],property2 [unit2] name1,4.5,2.3 name2,3.2,7.4 name3,5.5,6.1 最重要的是,我必须解释我使用的是Qt4.7,无法更新;此外,我无法安装Qxt,因此我依赖于JSON解析/编码。此外,CSV文件不是由我创建/维护的,因此我也不能真正更改它

有了这些,我意识到我需要一些东西,所以这是一个多重问题:

  • 我应该如何编写正则表达式来读取每列标题中的单位?请注意,该单位用右括号括起来
  • 假设我将标题行和其他行提取到一个
    QList
    ,将每一列作为字符串分隔。为了在QString上创建所需的JSON结构,如何同步所有数据位?(我想我需要在QString中使用它,这样我就可以将每一行转储到不同的文件中,但我也可以选择其他选项)
最后一个注意事项——我还需要注意这一点,以使其具有一定的可伸缩性。将应用此功能的CSV文件在列计数方面非常异构:有些文件有8列,有些文件有20列

我知道发布“多重问题”不是一个好的做法,但问题是我对所有这些都感到不知所措,因为我几乎没有使用Qt的经验,所以我甚至无法定义一个解决这个问题的计划。希望有人能分享一些建议。谢谢

编辑 因此,我一直在思考这个问题,我不知道这是否是一个好主意/可行,但以下是我的想法:

  • 在浏览标题行时,我会检查每个列字符串是否对正则表达式有影响。如果是这样,我会将列索引和单位字符串存储在一个列表中
  • 然后,在浏览其他行时,为了将它们解析为JSON,我会检查每一列是否与前面列表中的索引匹配,如果匹配,我会将该单元添加到映射中(正如qt JSON文档所解释的)
这有什么意义吗?有人能为我做一个骨骼模型吗

EDIT2

到目前为止,我已经设法使一些事情起作用,但仍然没有按它应该的那样起作用。现在,我已经成功地从CSV文件中正确读取,但是输出结果不正确。有人能分享一些见解吗

注意:processLineFromCSV函数返回一个获得的QStringList,如下所示:
QStringList cells=line.split(separator\u char)

注2:正则表达式从答案中获得

注3:检查下面我得到的输出类型。现在,我认为问题更多地与
qt-json
lib的使用有关,而不是与代码的其余部分有关,但是欢迎提供任何帮助!)

迄今为止的守则:

QFile file(csvfile);

    if (file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        bool first = true;
        QVariantMap map;
        QVariantMap propertyMap;
        QList<QVariant> generalList, propertiesList;

        while (!file.atEnd())
        {
            QString line = file.readLine();
            if(first == true){
                headerList = processLineFromCSV(line, separator_char);
                first = false;
            }else{

            QStringList cellList = processLineFromCSV(line, separator_char);

            int i=0;

            for(i; i<cellList.size(); i++)
            {
                // check the header cell for "[unit]" string
                // returns -1 if does not have the string
                // if it has the string, it's stored in capturedUnits[1]
                int test = exp.indexIn(headerList.at(i));

                // store the captured units in a QStringList
                QStringList capturedUnits = exp.capturedTexts();

                if(test==-1){ // if header does not have a captured unit - general column
                    QString name = headerList.at(i);
                    QString sanitizeName= name.remove(exp.capturedTexts().at(0), Qt::CaseSensitive);
                    map[sanitizeName] = cellList.at(i);
                }
                else{ // if header string has a captured unit - property column

                    QString propertyName = headerList.at(i); // extract string in header
                    QString sanitizedPropertyName = propertyName.remove(exp); //remove the unit regex from the string
                    sanitizedPropertyName.remove(QChar('\n'), Qt::CaseSensitive); // clear newlines

                    if(sanitizedPropertyName.startsWith('"') && sanitizedPropertyName.endsWith('"'))
                    {
                        sanitizedPropertyName.remove(0,1);
                        sanitizedPropertyName.remove(sanitizedPropertyName.length(),1);
                    }

                    QString value =cellList.at(i); // extract string in value
                    QString sanitizedValue = value.remove(QChar('\n'), Qt::CaseSensitive); // clear newlines

                    if(sanitizedValue.startsWith('"') && sanitizedValue.endsWith('"'))
                    {
                        sanitizedValue.remove(0,1);
                        sanitizedValue.remove(sanitizedValue.length(),1);
                    }

                    propertyMap[sanitizedPropertyName]= sanitizedValue; // map the property: value pair
                    propertyMap["unit"] = capturedUnits.at(1); // map the unit: [unit] value pair

                    QByteArray general = QtJson::serialize(map); // serialize the pair for general column
                    QByteArray properties = QtJson::serialize(propertyMap); // serialize the pair for property column

                    QVariant genVar(general);
                    QVariant propVar(properties);

                    generalList.append(genVar);
                    propertiesList.append(propVar);
                }
            }
        }}
        QByteArray finalGeneral = QtJson::serialize(generalList);
        QByteArray finalProperties = QtJson::serialize(propertiesList);

        qDebug() << finalGeneral;
        qDebug() << finalProperties;


        file.close();
    }
乔姆

刚刚看到你对我评论的回应。我对QT也没有太多的经验,但有一个快速的提纲

一次提取一行数据,并将其“拆分”为一个数组。如果您使用的是CSV,则需要确保数据点中没有逗号,否则分割将导致真正的混乱。检查提取数据的人是否可以使用另一个“不太常见”的分隔符(例如“|”是好的)。如果您的数据都是数字,这很好,但请注意使用逗号作为小数分隔符的位置:(

我希望每个文件有一个“表”,如果没有,您需要能够在新表启动时以某种方式“识别”,这可能很有趣/有趣-取决于您的outlook;)

最后你会有一个“字符串数组”(某种类型的表)的集合,希望第一个是你的头信息。如果您有多张表,您将一次处理一张

您现在应该能够以良好的JSON格式“输出”每个表

从标题行获取“单位”:如果您事先知道它们的位置(即数组中的索引),您可以计划在正确的索引位置提取信息(如果愿意,可以使用正则表达式)

最后一点。 如果您的csv文件很长(数百行),只需将前几行抓取到一个新的测试文件中,以便更快地进行调试,然后在您满意的情况下,将其放大一点并检查输出格式。。。然后再一次,当你很高兴没有其他的错误。。。整个文件 同样,如果文件中有多个表,请仅从第一个表开始,然后添加第二个表的第一部分。。。测试。。。。添加第三个。。。。测试等等,直到你高兴为止

大卫

在阅读您关于想要某种形式的“同步”的评论后,可能是更好的解决方案。 注意:这似乎有点复杂,但我认为它最终将是一个更灵活的解决方案。此外,如果某个数据库中不存在这些数据(谁给你的?),它们是否可以让你直接读取底层数据库和表?如果是这样,您可以直接跳到“将每个表输出到JSON”步骤

使用嵌入式数据库(即SQLite)。 提取第一个“header”行,并在数据库中创建一个表,该表遵循其中的信息(您应该能够将有关单位的信息添加到“metadata”即描述中)。如果所有文件都相同,您甚至可以将所有数据导入同一个表,或者使用相同的CREATETABLE语句为每个新文件自动创建一个新表(假定格式相同)

我确信SQLite中有一个“csvimport”(我还没有检查文档,并且有一段时间没有这样做),或者有人编写了一个库来实现这一点


将每个表输出为JSON格式,我确信有人已经为此编写了一个库。

这应该是一个好的开始:

QString csv = "name,property1 [unit1],property2 [unit2],property3 [unit3]\n"
              "name1,4.5,2.3\n"
              "name2,3.2,7.4\n"
              "name3,5.5,6.1,4.3\n";

QStringList csvRows = csv.split('\n', QString::SkipEmptyParts);
QStringList csvHeader = csvRows.takeFirst().split(',');
csvHeader.removeFirst();

foreach(QString row, csvRows) {
    QStringList values = row.split(',');
    QString rowName = values.takeFirst();

    QVariantList properties;
    for(int i = 0; i < values.size(); i++) {
        QString value = values[i];
        QStringList propParts = csvHeader[i].split(' ');
        QString propName = propParts[0];
        QString propType = propParts[1].mid(1, propParts[1].size() - 2);

        QVariantMap property;
        property[propName] = value;
        property["unit"] = propType;

        properties.append(property);
    }

    QVariantMap propertyObj;
    propertyObj["properties"] = properties;
    QVariantList propList;
    propList.append(propertyObj);

    QVariantMap root;
    root[rowName] = propList;

    QByteArray json = QtJson::serialize(root);
    qDebug() << json;

    // Now you can save json to a file
}
QString csv=“名称,属性1[unit1],属性2[unit2],属性3[unit3]\n”
“名称1,4.5,2.3\n”
“名称2,3.2,7.4\n”
“名称3,5.5,6.1,4.3\n”;
QStringList csvRows=csv.split('\n',QString::skipmptyparts);
QStringList csvHeader=csvRows.takeFirst().split(',');
csvHeader.removeFirst();
"[
    "{ \"name\" : \"name1\" }",
    "{ \"name\" : \"name1\" }",
    "{ \"name\" : \"name2\" }",
    "{ \"name\" : \"name2\" }",
    "{ \"name\" : \"name3\" }",
    "{ \"name\" : \"name3\" }"
]" 
"[
    "{ \"property1 \" : \"4.5\", \"unit\" : \"unit1\" }",
    "{ \"property1 \" : \"4.5\", \"property2 \" : \"2.3\", \"unit\" : \"unit2\" }",
    "{ \"property1 \" : \"3.2\", \"property2 \" : \"2.3\", \"unit\" : \"unit1\" }",
    "{ \"property1 \" : \"3.2\", \"property2 \" : \"7.4\", \"unit\" : \"unit2\" }",
    "{ \"property1 \" : \"5.5\", \"property2 \" : \"7.4\", \"unit\" : \"unit1\" }",
    "{ \"property1 \" : \"5.5\", \"property2 \" : \"6.1\", \"unit\" : \"unit2\" }"
]"
QString csv = "name,property1 [unit1],property2 [unit2],property3 [unit3]\n"
              "name1,4.5,2.3\n"
              "name2,3.2,7.4\n"
              "name3,5.5,6.1,4.3\n";

QStringList csvRows = csv.split('\n', QString::SkipEmptyParts);
QStringList csvHeader = csvRows.takeFirst().split(',');
csvHeader.removeFirst();

foreach(QString row, csvRows) {
    QStringList values = row.split(',');
    QString rowName = values.takeFirst();

    QVariantList properties;
    for(int i = 0; i < values.size(); i++) {
        QString value = values[i];
        QStringList propParts = csvHeader[i].split(' ');
        QString propName = propParts[0];
        QString propType = propParts[1].mid(1, propParts[1].size() - 2);

        QVariantMap property;
        property[propName] = value;
        property["unit"] = propType;

        properties.append(property);
    }

    QVariantMap propertyObj;
    propertyObj["properties"] = properties;
    QVariantList propList;
    propList.append(propertyObj);

    QVariantMap root;
    root[rowName] = propList;

    QByteArray json = QtJson::serialize(root);
    qDebug() << json;

    // Now you can save json to a file
}
QString csvfile = ui->lineEditCSVfile->text();
    QString separator_char = ui->lineEditSeparator->text();
    QRegExp exp("\\[([^\\]]+)\\]");

    QFile file(csvfile);
     if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
         return;

    QString csv = file.readAll();

    QStringList csvRows = csv.split('\n', QString::SkipEmptyParts);

    QStringList csvHeader = csvRows.takeFirst().split(separator_char);

    csvHeader.removeFirst();

    foreach(QString row, csvRows) {
        QStringList values = row.split(separator_char);

        QString rowName = values.takeFirst();

        QVariantList general;
        QVariantList properties;
        for(int i = 0; i < values.size(); i++) {
            QString value = values[i];

            int test = exp.indexIn(csvHeader[i]);
            //qDebug() << test;

            //qDebug() << csvHeader;
            QStringList capturedUnits = exp.capturedTexts();
            QString propName = csvHeader[i];


            if(test==-1){
                //QString propName = csvHeader[i].remove(exp);
                //qDebug() <<"property name" << propName;

                QVariantMap property;
                property[propName] = value;
                general.append(property);
            }else{
                propName.remove(exp);
                //QStringList propParts = csvHeader[i].split(' ');
                //QString propName = csvHeader[i].remove(exp);
                QString propType = capturedUnits[1];

                QVariantMap property;
                property[propName] = value;
                property["unit"] = propType;

                properties.append(property);
            }
        }

        QVariantMap propertyObj;
        propertyObj["properties"] = properties;
        QVariantList propList;
        propList.append(propertyObj);

        QVariantMap generalObj;
        generalObj["general"] = general;
        QVariantList generalList;
        generalList.append(generalObj);

        QVariantList fullList;
        fullList.append(generalObj);
        fullList.append(propertyObj);

        QVariantMap root;
        root[rowName] = fullList;

        QByteArray json = QtJson::serialize(root);

        json.prepend('[');
        json.append(']');

        qDebug() << json;

        // Now you can save json to a file