Parsing through a csv file in Qt

后端 未结 6 1856
忘掉有多难
忘掉有多难 2020-12-09 04:42

Is anyone familiar with how to parse through a csv file and put it inside a string list. Right now I am taking the entire csv file and putting into the string list. I am try

6条回答
  •  孤街浪徒
    2020-12-09 05:27

    Here is the code I usually use. I'm the author, consider this as-is, public domain. It has a similar feature-set and concept as CodeLurker's code except the state machine is represented differently, the code is a bit shorter.

    bool readCSVRow (QTextStream &in, QStringList *row) {
    
        static const int delta[][5] = {
            //  ,    "   \n    ?  eof
            {   1,   2,  -1,   0,  -1  }, // 0: parsing (store char)
            {   1,   2,  -1,   0,  -1  }, // 1: parsing (store column)
            {   3,   4,   3,   3,  -2  }, // 2: quote entered (no-op)
            {   3,   4,   3,   3,  -2  }, // 3: parsing inside quotes (store char)
            {   1,   3,  -1,   0,  -1  }, // 4: quote exited (no-op)
            // -1: end of row, store column, success
            // -2: eof inside quotes
        };
    
        row->clear();
    
        if (in.atEnd())
            return false;
    
        int state = 0, t;
        char ch;
        QString cell;
    
        while (state >= 0) {
    
            if (in.atEnd())
                t = 4;
            else {
                in >> ch;
                if (ch == ',') t = 0;
                else if (ch == '\"') t = 1;
                else if (ch == '\n') t = 2;
                else t = 3;
            }
    
            state = delta[state][t];
    
            switch (state) {
            case 0:
            case 3:
                cell += ch;
                break;
            case -1:
            case 1:
                row->append(cell);
                cell = "";
                break;
            }
    
        }
    
        if (state == -2)
            throw runtime_error("End-of-file found while inside quotes.");
    
        return true;
    
    }
    
    • Parameter: in, a QTextStream.
    • Parameter: row, a QStringList that will receive the row.
    • Returns: true if a row was read, false if EOF.
    • Throws: std::runtime_error if an error occurs.

    It parses Excel style CSV's, handling quotes and double-quotes appropriately, and allows newlines in fields. Handles Windows and Unix line endings properly as long as your file is opened with QFile::Text. I don't think Qt supports old-school Mac line endings, and this doesn't support binary-mode untranslated line-endings, but for the most part this shouldn't be a problem these days.

    Other notes:

    • Unlike CodeLurker's implementation this intentionally fails if EOF is hit inside quotes. If you change the -2's to -1's in the state table then it will be forgiving.
    • Parses x"y"z as xyz, wasn't sure what the rule for mid-string quotes was. I have no idea if this is correct.
    • Performance and memory characteristics the same as CodeLurker's (i.e. very good).
    • Does not support unicode (converts to ISO-5589-1) but changing to QChar should be trivial.

    Example:

    QFile csv(filename);
    csv.open(QFile::ReadOnly | QFile::Text);
    
    QTextStream in(&csv);
    QStringList row;
    while (readCSVRow(in, &row))
        qDebug() << row;
    

提交回复
热议问题