Синтаксический анализ 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;
}
-
:
- возвращает:
true
если строка была прочитана,false
если ВФ. - Броски:
std::runtime_error
при возникновении ошибки.
in
, a QTextStream
.
: row
, a QStringList
это получит строку.
он анализирует CSV-файлы стиля Excel, обрабатывает кавычки и двойные кавычки соответствующим образом и позволяет создавать новые строки в полях. Обрабатывает окончания строк Windows и Unix правильно, пока ваш файл открыт с QFile::Text
. Я не думаю, что Qt поддерживает старомодные окончания строк Mac, и это не поддерживает непереведенные окончания строк в двоичном режиме, но по большей части это не должно быть проблемой в эти дни.
другой Примечания:
- в отличие от реализации CodeLurker это намеренно терпит неудачу, если EOF попадает внутрь кавычек. Если вы измените -2 на -1 в таблице состояний, то это будет прощение.
- анализ
x"y"z
asxyz
, не был уверен, что правило для средних строковых кавычек было. Я понятия не имею, правильно ли это. - характеристики производительности и памяти такие же, как у 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