在Qt中解析csv文件

pkwftd7m  于 2022-12-06  发布在  其他
关注(0)|答案(6)|浏览(299)

有人熟悉如何解析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();
}
disho6za

disho6za1#

这就对了:

飞行参数.csv

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

主文件. 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;
}

第1001章:我的main.pro

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

生成并运行

qmake && make && ./main

输出

("1", "4", "7")
6yt4nkrj

6yt4nkrj2#

你要找的是一个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();
5lhxktic

5lhxktic3#

这是我经常使用的代码。我是作者,按原样考虑这个,公共域(gist)。它与CodeLurker's code具有相似的特性集和概念,除了状态机的表示方式不同,代码稍短。

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];

        if (state == 0 || state == 3) {
            cell += ch;
        } else if (state == -1 || state == 1) {
            row->append(cell);
            cell = "";
        }

    }

    if (state == -2)
        throw runtime_error("End-of-file found while inside quotes.");

    return true;

}
  • 参数:in,一个QTextStream
  • 参数:row,将接收行的QStringList
  • 如果读取了行,则返回:true;如果EOF,则返回false
  • 如果发生错误,则引发:std::runtime_error

它可以解析Excel风格的CSV文件,正确处理引号和双引号,并允许在字段中换行。只要你的文件是用QFile::Text打开的,它就可以正确处理Windows和Unix的行尾。我认为Qt不支持老式的Mac行尾,也不支持二进制模式的未翻译行尾,但现在大多数情况下这应该不是问题。
其他注意事项:

  • 与CodeLurker的实现不同,如果EOF在引号内被命中,这会故意失败。如果你在状态表中将-2改为-1,那么它将是宽容的。
  • x"y"z解析为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;
kx1ctssn

kx1ctssn4#

人们可能更喜欢这样做:

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

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

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

            // Double-quote
            else if (current == '"')
            {
                state = Quote;
                value += current;
            }

            // Other character
            else
                value += current;
        }

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

                        // Skip a second quote character in a row
                        i++;
                    }
                    else
                    {
                        state = Normal;
                        value += '"';
                    }
                }
            }

            // Other character
            else
                value += current;
        }
    }

    if (!value.isEmpty())
        fields.append(value.trimmed());

    // Quotes are left in until here; so when fields are trimmed, only whitespace outside of
    // quotes is removed.  The outermost quotes are removed here.
    for (int i=0; i<fields.size(); ++i)
        if (fields[i].length()>=1 && fields[i].left(1)=='"')
        {
            fields[i]=fields[i].mid(1);
            if (fields[i].length()>=1 && fields[i].right(1)=='"')
                fields[i]=fields[i].left(fields[i].length()-1);
        }

    return fields;
}
  • 功能强大:使用逗号、双引号(表示双引号字符)和右空格处理引用的内容
  • 灵活:即使忘记了最后一个字符串的最后一个引号也不会失败,并且可以处理更复杂的CSV文件;允许您一次处理一行,而不必先读取内存中的整个文件
  • 简单:只需将此状态机放到您的代码中,右键单击QtCreator中的函数名,然后选择“重构|添加私有声明,然后yergood 2就可以了。
  • 高性能:准确处理CSV行,比对每个字符执行RegEx先行查找更快
  • 方便:不需要外部库
  • 易于阅读:代码是直观的,在情况下U需要2修改它.

编辑:我终于有时间来修剪字段前后的空格了。引号内的空格和逗号都不会被修剪。否则,所有的空格都会从字段的开始和结束处被修剪。在对这个问题困惑了一段时间后,我突然想到可以在字段周围留下引号;和文本前后的空白被删除,然后添加最后一步,去掉以引号开头和结尾的字段的引号。
下面是一个或多或少具有挑战性的测试用例:

QStringList sl=
{
    "\"one\"",
    "  \" two \"\"\"  , \" and a half  ",
    "three  ",
    "\t  four"
};

for (int i=0; i < sl.size(); ++i)
    qDebug() << parseCSV(sl[i]);

这对应于文件

"one"
 " two """  , " and a half  
three  
<TAB>  four

其中表示制表符;并且每一行都被依次送入parseCSV()。不要这样写.csv文件!
它的输出是(其中qDebug()用\"表示字符串中的引号,并将内容放在引号和括号中):

("one")
(" two \"", " and a half")
("three")
("four")

您可以观察到,引号和额外的空格保留在条目“two”的引号内。在“and a half”的格式错误的情况下,引号之前的空格和最后一个单词之后的空格被删除;但其他字段没有。此例程中缺少结尾空格可能表示缺少结尾引号。字段中没有开始或结束的引号只被视为字符串的一部分。如果引号不是字段的开头,则不会从字段的结尾删除引号。若要检测此处的错误,只需检查以引号开始但不以引号结束的字段;和/或包含引号但不以引号开头和结尾的字符串。
我知道,这比你的测试案例所需要的要多;但是,一个坚实的一般答案?,尽管如此-也许对其他人谁已经发现了它。
改编自:https://github.com/hnaohiro/qt-csv/blob/master/csv.cpp

ndasle7k

ndasle7k5#

尝试使用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文件中的库文档和其他代码示例。

vc6uscn9

vc6uscn96#

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

然后

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

我不确定add函数是否存在,是否要添加到数组中-让我们调用第1列

相关问题