Qt解析复杂的csv格式文件

3 篇文章 0 订阅

/*csv格式是以逗号分隔列的。
* 每行内容是以换行符作为一行的。
* 如果内容中包含换行符,则整个内容要以双引号括起来。
* 如果内容中包含逗号,则整个内容要以双引号括起来。
* 如果内容中又有双引号,则会是2个双引号连在一起表示一个双引号。
* 每个字段的左右2边的空白字符可以忽略。
* 还有其他复杂的情况,暂时不考虑
*/
/*针对以上csv的复杂多变的格式,我们这里只考虑以下几种情况吧:
* 1. 逗号分隔列。
* 2. 某个列的内容可能多行显示。
* 3. 某个列可能存在逗号、双引号、换行。
*/

QList<QStringList> parseCSVFile(const QString &strFile)
{
    QList<QStringList> allRecordSets;
    QFile file(strFile);
    if (!file.open(QFile::ReadOnly)) return allRecordSets;
    QTextStream ins(&file);

    bool bInQuote = false;
    const QChar chQuote('\"');
    const QChar chEnter('\n');
    const QChar chComma(',');

    int iFileLineCount = 0;
    QStringList currentRecordset;
    QString strFieldData;
    while (!ins.atEnd())
    {
        ++iFileLineCount;
        const QString strLine = ins.readLine()+'\n'; //QTextStream::readLine()去掉了换行符
        for (int i=0; i<strLine.size(); ++i)
        {
            const QChar c = strLine.at(i);
            if (chComma == c)
            {
                if (bInQuote)
                {
                    strFieldData.append(c);
                }
                else
                {
                    strFieldData = strFieldData.trimmed(); //去掉左右两边的空白字符
                    currentRecordset.append(strFieldData);
                    strFieldData = "";
                }
            }
            else if (chEnter == c)
            {
                if (bInQuote)
                {
                    strFieldData.append(c);
                }
                else
                {
                    strFieldData = strFieldData.trimmed(); //去掉左右两边的空白字符
                    currentRecordset.append(strFieldData);
                    allRecordSets.append(currentRecordset);
                    strFieldData = "";
                    currentRecordset.clear();
                }
            }
            else if (chQuote == c)
            {
                //由于strLine的最后一个字符一定是'\n',所以strLine.at(i+1)肯定不会越界,所以无需判断越界。
                if (bInQuote)
                {//当前字符是双引号,且最开始已经有双引号,则当前字符可能是字段内容,也可能是字段结束位置
                    QChar next = strLine.at(i+1);
                    if (chQuote == next)
                    {//当前字符的下一个字符是双引号,说明是字段内容的一部分
                        strFieldData.append(c);
                        ++i;
                    }
                    else if (chEnter == next)
                    {//当前字符的下一个字符是换行,说明当前的一条记录解析完毕
                        bInQuote = false;
                    }
                    else if (chComma == next)
                    {//当前字符的下一个字符是逗号,说明当前字段解析完毕
                        bInQuote = false;
                    }
                    else if (next.isSpace())
                    {//双引号结束的情况下,如果当前字符的下一个字符是空白字符,则忽略
                        for(++i;i<strLine.size();)
                        {
                            next = strLine.at(i);
                            if (next.isSpace() && next!=chEnter)
                            {//是空白字符但不是换行
                                ++i;
                            }
                            else
                            {
                                --i; //便于下一个解析,所以指针回退。
                                break;
                            }
                        }
                        bInQuote = false;
                    }
                    else
                    {//说明格式有问题
                        qDebug().noquote().nospace()<<QString("the csv file(%1)(line=%2) has format error").arg(strFile).arg(iFileLineCount);
                        strFieldData.append(c);
                    }
                }
                else
                {//表示字段的开始
                    bInQuote = true;
                }
            }
            else
            {
                strFieldData.append(c);
            }
        }
    }
    return allRecordSets;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt5 是一款功能强大的跨平台应用程序开发框架,它提供了丰富的库和工具来简化应用程序的开发。要解析 CSV 文件,可以使用 Qt5 中提供的 QFile 和 QTextStream 类。 首先,我们需要打开 CSV 文件并创建 QFile 对象。可以通过传入文件路径作为参数来实现,然后调用 QFile 的 open() 函数打开文件。 ```cpp QFile file("file.csv"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { // 文件打开失败的处理逻辑 return; } ``` 接下来,我们可以创建 QTextStream 对象并将 QFile 对象作为参数传入。使用 QTextStream 可以方便地按行读取 CSV 文件的内容。 ```cpp QTextStream in(&file); while (!in.atEnd()) { QString line = in.readLine(); // 对读取到的每行内容进行处理 } ``` 在处理每行内容之前,我们可以将 line 字符串按照逗号分隔符进行拆分。可以使用 QString 的 split() 函数将一行内容拆分为多个字段。 ```cpp QStringList fields = line.split(","); foreach (QString field, fields) { // 处理每个字段 } ``` 当然,还需要根据实际的 CSV 文件格式进行适当的处理。例如,有些 CSV 文件在字段中包含逗号,这会干扰拆分。在这种情况下,可能需要使用正则表达式或其他方法来处理字段。 完成对字段内容的处理后,就可以在应用程序中使用了。可以将字段存储在适当的数据结构中,如 QStringList 或 QVector 中,以供后续使用。 最后,在处理完 CSV 文件后,别忘了关闭打开的文件。 ```cpp file.close(); ``` 通过使用 QFile 和 QTextStream,我们可以轻松地解析并处理 CSV 文件中的内容。Qt5 提供了对文件的方便访问和处理,使得解析 CSV 文件变得简单高效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值