Qt解析CSV文件

最近需要解析Excel文件,于是顺带写了解析CSV的代码

定义数据类型LX::Sheet

#ifndef LX_H
#define LX_H

#include <QString>
#include <QStringList>

namespace LX
{
class Sheet
{
    enum FieldType{STRING, INT, DOUBLE, BOOL};
public:
    Sheet(){}
    Sheet(Sheet&& rhs);
    Sheet &operator =(Sheet &&rhs);
public:
    QString name;
    QList<QStringList> data;
    QList<FieldType> fieldTypes;
};
}

#endif // LX_H

 
解析CSV文件

LX::Sheet FileParse::parseCSV(const QString &fileName)
{
    LX::Sheet sheet;

    int nameStartIndex = fileName.lastIndexOf('/') + 1;
    if(nameStartIndex < 1)
    {
        nameStartIndex = fileName.lastIndexOf('\\') + 1;
    }
    int nameEndIndex = fileName.lastIndexOf('.');
    sheet.name = fileName.mid(nameStartIndex, nameEndIndex - nameStartIndex);

    QFile file(fileName);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return sheet;
    }

    QTextStream inStream(&file);

    for( QString lineStr; !inStream.atEnd(); )
    {
        lineStr = inStream.readLine();
        if(lineStr.isEmpty())
        {
            continue;
        }

        sheet.data.append(splitCSVLine(lineStr));
    }

    return qMove(sheet);
}

QStringList FileParse::splitCSVLine(const QString &lineStr)
{
    QStringList strList;
    QString str;

    int length = lineStr.length();
    int quoteCount = 0;
    int repeatQuoteCount = 0;

    for(int i = 0; i < length; ++i)
    {
        if(lineStr[i] != '\"')
        {
            repeatQuoteCount = 0;
            if(lineStr[i] != ',')
            {
                str.append(lineStr[i]);
            }
            else
            {
                if(quoteCount % 2)
                {
                    str.append(',');
                }
                else
                {
                    strList.append(str);
                    quoteCount = 0;
                    str.clear();
                }
            }
        }
        else
        {
            ++quoteCount;
            ++repeatQuoteCount;
            if(repeatQuoteCount == 4)
            {
                str.append('\"');
                repeatQuoteCount = 0;
                quoteCount -= 4;
            }
        }
    }
    strList.append(str);

    return qMove(strList);
}

 

生成CSV文件

bool FileParse::generateCSV(const QString &fileName, const LX::Sheet &sheet)
{
    QFile file(fileName);
    bool openOk = file.open(QIODevice::WriteOnly);
    if(!openOk)
    {
        return false;
    }
    QTextStream outStream(&file);

    int strCount = sheet.data.count();
    for(int i = 0; i < strCount; ++i)
    {
        outStream << joinCSVStrs(sheet.data.at(i));
        outStream << '\n';
    }

    return true;
}

 

QString FileParse::joinCSVStrs(const QStringList &strList)
{
    QString lineStr;

    int strCount = strList.count();
    int lastStrIndex = strCount - 1;

    for(int k = 0; k < strCount; ++k)
    {
        QString tarStr;
        bool commaFlag = false;

        const QString& oriStr = strList.at(k);
        int length = oriStr.length();
        for(int i = 0; i < length; ++i)
        {
            if(oriStr[i] == ',')
            {
                tarStr.append(oriStr[i]);
                commaFlag = true;
            }
            else if(oriStr[i] == '\"')
            {
                tarStr.append("\"\"\"\"");
            }
            else
            {
                tarStr.append(oriStr[i]);
            }
        }
        if(commaFlag)
        {
            tarStr.push_front('\"');
            tarStr.push_back('\"');
        }
        if(k != lastStrIndex)
        {
            tarStr.append(',');
        }

        lineStr.append(tarStr);
    }

    return qMove(lineStr);
}

 

解析规则为:

1、若逗号间无数据,仍解释为空数据

2、若字段中含有逗号则用"将字段包含起来

3、若数据中存在 " ,则将其替换为 """"

posted on 2015-01-27 12:47  lixtary  阅读(6711)  评论(0编辑  收藏  举报

导航