Синтаксический анализ csv-файла в Qt

кто-нибудь знаком с тем, как анализировать csv-файл и помещать его в список строк. Прямо сейчас я беру весь csv-файл и помещаю в список строк. Я пытаюсь выяснить, есть ли способ получить только первый столбец.

#include "searchwindow.h"
#include <QtGui/QApplication>

#include <QApplication>
#include <QStringList>
#include <QLineEdit>
#include <QCompleter>
#include <QHBoxLayout>
#include <QWidget>
#include <QLabel>

#include <qfile.h>
#include <QTextStream>


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWidget *widget = new QWidget();
    QHBoxLayout *layout = new QHBoxLayout();

    QStringList wordList;

    QFile f("FlightParam.csv");
    if (f.open(QIODevice::ReadOnly))
    {
        //file opened successfully
        QString data;
        data = f.readAll();
        wordList = data.split(',');

        f.close();
    }

    QLabel *label = new QLabel("Select");
    QLineEdit *lineEdit = new QLineEdit;
    label->setBuddy(lineEdit);

    QCompleter *completer = new QCompleter(wordList);
    completer->setCaseSensitivity(Qt::CaseInsensitive); //Make caseInsensitive selection

    lineEdit->setCompleter(completer);

    layout->addWidget(label);
    layout->addWidget(lineEdit);

    widget->setLayout(layout);
    widget->showMaximized();

    return a.exec();
}

6 ответов


вот так:

FlightParam.csv

1,2,3,
4,5,6,
7,8,9,

main.cpp

#include <QFile>
#include <QStringList>
#include <QDebug>

int main()
{
    QFile file("FlightParam.csv");
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << file.errorString();
        return 1;
    }

    QStringList wordList;
    while (!file.atEnd()) {
        QByteArray line = file.readLine();
        wordList.append(line.split(',').first());
    }

    qDebug() << wordList;

    return 0;
}

главная.про

TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp

построить и запустить

qmake && make && ./main

выход

("1", "4", "7")

то, что вы ищете-это QTextStream класса. Он предоставляет все виды интерфейсов для чтения и записи файлов.

простой пример:

QStringList firstColumn;
QFile f1("h:/1.txt");
f1.open(QIODevice::ReadOnly);
QTextStream s1(&f1);
while (!s1.atEnd()){
  QString s=s1.readLine(); // reads line from file
  firstColumn.append(s.split(",").first()); // appends first column to list, ',' is separator
}
f1.close();

альтернативно да, вы можете сделать что-то вроде этого, которое будет иметь тот же результат:

wordList = f.readAll().split(QRegExp("[\r\n]"),QString::SkipEmptyParts); //reading file and splitting it by lines
for (int i=0;i<wordList.count();i++) 
   wordList[i]=wordlist[i].split(",").first(); // replacing whole row with only first value
f.close();    

попробовать qtcsv библиотека для чтения и записи CSV-файлов. Пример:

#include <QList>
#include <QStringList>
#include <QDir>
#include <QDebug>

#include "qtcsv/stringdata.h"
#include "qtcsv/reader.h"
#include "qtcsv/writer.h"

int main()
{
    // prepare data that you want to save to csv-file
    QStringList strList;
    strList << "one" << "two" << "three";

    QtCSV::StringData strData;
    strData.addRow(strList);
    strData.addEmptyRow();
    strData << strList << "this is the last row";

    // write to file
    QString filePath = QDir::currentPath() + "/test.csv";
    QtCSV::Writer::write(filePath, strData);

    // read data from file
    QList<QStringList> readData = QtCSV::Reader::readToList(filePath);
    for ( int i = 0; i < readData.size(); ++i )
    {
        qDebug() << readData.at(i).join(",");
    }

    return 0;
}

Я попытался сделать его маленьким и простым в использовании. См.Readme файл для документации библиотеки и других примеров кода.


можно было бы сделать это так:

QStringList MainWindow::parseCSV(const QString &string)
{
    enum State {Normal, Quote} state = Normal;
    QStringList fields;
    QString value;

    for (int i = 0; i < string.size(); i++)
    {
        QChar current = string.at(i);

        // Normal state
        if (state == Normal)
        {
            // Comma
            if (current == ',')
            {
                // Save field
                fields.append(value);
                value.clear();
            }

            // Double-quote
            else if (current == '"')
                state = Quote;

            // Other character
            else
                value += current;
        }

        // In-quote state
        else if (state == Quote)
        {
            // Another double-quote
            if (current == '"')
            {
                if (i+1 < string.size())
                {
                    QChar next = string.at(i+1);

                    // A double double-quote?
                    if (next == '"')
                    {
                        value += '"';
                        i++;
                    }
                    else
                        state = Normal;
                }
            }

            // Other character
            else
                value += current;
        }
    }
    if (!value.isEmpty())
        fields.append(value);

    return fields;
}
  • мощный: обрабатывает цитируемый материал запятыми и двойными двойными кавычками (которые означают символ двойной кавычки) справа
  • гибкий: не терпит неудачу, если последняя цитата в последней строке забыта и обрабатывает более сложные CSV-файлы; позволяет обрабатывать одну строку за раз без необходимости сначала читать весь файл в памяти
  • простой: просто поместите эту государственную машину в свой код, щелкните правой кнопкой мыши на имя функции в QtCreator и выберите Refactor / Add public declaration, и yer good 2 go
  • Performant: точно обрабатывает CSV-строки быстрее, чем делает RegEx look-aheads на каждом символе
  • удобный: не требует никакой внешней библиотеки

Примечание: этот метод не обрезает пробелы до или после поля. Я планирую улучшить его в среднесрочном будущем (или не стесняйтесь), чтобы удалить пробелы до первой цитаты и после последней. Также, если кавычек нет, пробелы можно обрезать. При этом я обычно не нахожу пробелов до или после кавычек в CSV-файле, сгенерированном программой; а состояние кавычки позволяет включать запятые в текстовое литеральное поле.

больше, чем было необходимо для вашего тестового случая, я знаю; но твердый общий ответ на ? тем не менее - возможно, для тех, кто его нашел.

адаптировано из: https://github.com/hnaohiro/qt-csv/blob/master/csv.cpp


вот код, который я обычно использую. Я автор, считайте это общественным достоянием. Он имеет аналогичный набор функций и понятие как код CodeLurker за исключением того, что государственная машина представлена по-другому, код немного короче.

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;

}
    : in, a QTextStream. : row, a QStringList это получит строку.
  • возвращает: true если строка была прочитана, false если ВФ.
  • Броски: std::runtime_error при возникновении ошибки.

он анализирует CSV-файлы стиля Excel, обрабатывает кавычки и двойные кавычки соответствующим образом и позволяет создавать новые строки в полях. Обрабатывает окончания строк Windows и Unix правильно, пока ваш файл открыт с QFile::Text. Я не думаю, что Qt поддерживает старомодные окончания строк Mac, и это не поддерживает непереведенные окончания строк в двоичном режиме, но по большей части это не должно быть проблемой в эти дни.

другой Примечания:

  • в отличие от реализации CodeLurker это намеренно терпит неудачу, если EOF попадает внутрь кавычек. Если вы измените -2 на -1 в таблице состояний, то это будет прощение.
  • анализ x"y"z as xyz, не был уверен, что правило для средних строковых кавычек было. Я понятия не имею, правильно ли это.
  • характеристики производительности и памяти такие же, как у CodeLurker (т. е. очень хорошие).
  • не поддерживает unicode (преобразуется в ISO-5589-1), но меняется к QChar должно быть тривиальным.

пример:

QFile csv(filename);
csv.open(QFile::ReadOnly | QFile::Text);

QTextStream in(&csv);
QStringList row;
while (readCSVRow(in, &row))
    qDebug() << row;

lines = data.split('\n');

затем

for line in lines
   column1.add(line.split(',')[0])

Я не уверен, что функция add существует или не добавляется в массив-пусть вызовет столбец 1