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();
}
そこに行きます:
1,2,3,
4,5,6,
7,8,9,
#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();
私が通常使用するコードは次のとおりです。私は著者であり、これを現状のままのパブリックドメインと考えています。 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
、行を受け取るQStringList
。true
、EOFの場合はfalse
。std::runtime_error
エラーが発生した場合。ExcelスタイルのCSVを解析し、引用符と二重引用符を適切に処理し、フィールドに改行を追加します。ファイルがQFile::Text
で開かれている限り、WindowsおよびUnixの行末を適切に処理します。 Qtは昔ながらのMacの行末をサポートしておらず、これはバイナリモードの未翻訳の行末をサポートしていませんが、ほとんどの場合、これは最近では問題になりません。
その他の注意事項:
x"y"z
をxyz
として解析しますが、中央文字列引用符のルールが何であるかわかりませんでした。これが正しいかどうかはわかりません。QChar
への変更は簡単です。例:
QFile csv(filename);
csv.open(QFile::ReadOnly | QFile::Text);
QTextStream in(&csv);
QStringList row;
while (readCSVRow(in, &row))
qDebug() << row;
次の方法でそれを行うことを好むかもしれません:
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 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;
}
編集:私はようやくこれを取得して、フィールドの前後のスペースをトリミングすることになりました。引用符内の空白やカンマは削除されません。それ以外の場合、すべての空白はフィールドの先頭と末尾から削除されます。これについてしばらく困惑した後、引用符がフィールドの周りに残る可能性があるという考えに思いつきました。そのため、すべてのフィールドをトリミングできます。これにより、引用符の前後の空白のみが削除されます。その後、最後のステップが追加され、引用符で始まるフィールドと引用符で終わるフィールドの引用符が取り除かれました。
多少難易度の高いテストケースを次に示します。
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
ここで、<TAB>はタブ文字を表します。そして、各行はparseCSV()に順番に送られます。このような.csvファイルを書き込まないでください!
出力は次のとおりです(qDebug()は文字列内の引用符を\"
で表し、引用符と括弧で囲みます):
("one")
(" two \"", " and a half")
("three")
("four")
引用符と余分なスペースが、アイテム「two」の引用符内に保持されていることがわかります。 「と半分」の不正なケースでは、引用の前のスペースと最後のワードの後のスペースが削除されました。しかし、他はそうではありませんでした。このルーチンで端末スペースが欠落している場合、端末引用符が欠落している可能性があります。開始または終了しないフィールド内の引用符は、文字列の一部として扱われます。引用符は、フィールドを開始しない場合、フィールドの末尾から削除されません。ここでエラーを検出するには、引用符で始まり、引用符で終わらないフィールドをチェックするだけです。および/または、最後のループで引用符を含むもので始まり、引用符で始まり終わらないもの。
Yerテストケースに必要だった以上のものを知っています。しかし、?に対する堅実な一般的な答えは、それでも-それを見つけた他の人にとってはおそらくでしょう。
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 ファイルを参照してください。
lines = data.split('\n');
それから
for line in lines
column1.add(line.split(',')[0])
関数が存在するかどうか、配列に追加しないかどうかはわかりません-列1を呼び出してください