Qt解析复杂的csv格式文件

/*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;
}

相关推荐

  1. Qt解析复杂csv格式文件

    2024-07-19 07:20:05       19 阅读
  2. Python中写入csv格式文件出现乱码解决方法

    2024-07-19 07:20:05       50 阅读
  3. SpringBoot整合easyExcel实现CSV格式文件导入导出

    2024-07-19 07:20:05       63 阅读
  4. Python对csv格式文件保存与读取

    2024-07-19 07:20:05       31 阅读
  5. Qt解析json格式数据

    2024-07-19 07:20:05       33 阅读
  6. [Qt]解析moc文件

    2024-07-19 07:20:05       25 阅读
  7. 解决PyCharm中文件格式关联错误:终极指南

    2024-07-19 07:20:05       18 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 07:20:05       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 07:20:05       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 07:20:05       58 阅读
  4. Python语言-面向对象

    2024-07-19 07:20:05       69 阅读

热门阅读

  1. 日常遇到的英文单词四

    2024-07-19 07:20:05       18 阅读
  2. zookeeper+kafka消息队列群集部署

    2024-07-19 07:20:05       21 阅读
  3. 侧开知识点合集2

    2024-07-19 07:20:05       18 阅读
  4. .net core IConfiguration 读 appsettings.json 数据,举例

    2024-07-19 07:20:05       22 阅读
  5. C# 多线程

    2024-07-19 07:20:05       13 阅读
  6. ES6 模块

    2024-07-19 07:20:05       16 阅读
  7. Armpro搭建教程全开源版的教程

    2024-07-19 07:20:05       24 阅读
  8. git实现多人协作开发同一个项目

    2024-07-19 07:20:05       22 阅读
  9. GitHub介绍

    2024-07-19 07:20:05       20 阅读
  10. 前端入门(一)环境搭建

    2024-07-19 07:20:05       17 阅读
  11. MySQL中的数据类型

    2024-07-19 07:20:05       22 阅读
  12. ESC(ELectronic Stability Control,电子稳定控制系统)

    2024-07-19 07:20:05       20 阅读