Regex 使用正则表达式从CSV提取数据并将其转换为JSON
假设您在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文件不是由我创建/维护的,因此我也不能真正更改它 有了这些,我意识到我需要一些东西,所以这是一个多重问题: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文件不是由我创建/维护的,因此我也不能真正更改它 有了这些,我意识到我需要一些东西,所以这是一个多重问题: 我应该如何编写正则表达式来读取每列标题中的单位?请注意,
- 我应该如何编写正则表达式来读取每列标题中的单位?请注意,该单位用右括号括起来
- 假设我将标题行和其他行提取到一个
,将每一列作为字符串分隔。为了在QString上创建所需的JSON结构,如何同步所有数据位?(我想我需要在QString中使用它,这样我就可以将每一行转储到不同的文件中,但我也可以选择其他选项)QList
- 在浏览标题行时,我会检查每个列字符串是否对正则表达式有影响。如果是这样,我会将列索引和单位字符串存储在一个列表中李>
- 然后,在浏览其他行时,为了将它们解析为JSON,我会检查每一列是否与前面列表中的索引匹配,如果匹配,我会将该单元添加到映射中(正如qt JSON文档所解释的)
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