Quelqu'un sait-il comment analyser un fichier csv et le placer dans une liste de chaînes? En ce moment, je prends le fichier csv entier et je le mets dans la liste des chaînes. J'essaie de comprendre s'il existe un moyen d'obtenir uniquement la première colonne.
#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();
}
Voilà:
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")
Ce que vous recherchez est une classe QTextStream . Il fournit toutes sortes d'interfaces pour lire et écrire des fichiers.
Un exemple simple:
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();
Alternativement oui, vous pouvez faire quelque chose comme ça qui aurait le même résultat:
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();
Voici le code que j'utilise habituellement. Je suis l'auteur, considérez-le comme tel, dans le domaine public. Il a un ensemble de fonctionnalités et un concept similaires à code de CodeLurker sauf que la machine d'état est représentée différemment, le code est un peu plus court.
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 if (ch == '\r') continue;
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
, un QStringList
qui recevra la ligne.true
si une ligne a été lue, false
si EOF.std::runtime_error
si une erreur se produit.Il analyse les fichiers CSV de style Excel, gère les guillemets et les guillemets de manière appropriée et autorise les retours à la ligne dans les champs. Gère correctement les fins de ligne Windows et Unix tant que votre fichier est ouvert avec QFile::Text
. Je ne pense pas que Qt prend en charge les terminaisons de ligne Mac à l'ancienne, et cela ne prend pas en charge les terminaisons de ligne non traduites en mode binaire, mais pour la plupart, cela ne devrait pas être un problème de nos jours.
Autres notes:
x"y"z
as xyz
, ne savait pas quelle était la règle pour les guillemets intermédiaires. Je n'ai aucune idée si c'est correct.QChar
devrait être trivial.Exemple:
QFile csv(filename);
csv.open(QFile::ReadOnly | QFile::Text);
QTextStream in(&csv);
QStringList row;
while (readCSVRow(in, &row))
qDebug() << row;
On pourrait préférer le faire de cette façon:
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;
}
Edit: j'ai enfin réussi à obtenir ceci pour couper les espaces avant et après les champs. Aucun espace ni virgule n'est coupé à l'intérieur des guillemets. Sinon, tous les espaces sont coupés au début et à la fin d'un champ. Après avoir été perplexe à ce sujet pendant un certain temps, j'ai trouvé l'idée que les citations pourraient être laissées sur le terrain; et ainsi tous les champs pourraient être coupés. De cette façon, seuls les espaces avant et après les guillemets ou le texte sont supprimés. Une dernière étape a ensuite été ajoutée, pour supprimer les citations des champs qui commencent et se terminent par des citations.
Voici un cas de test plus ou moins difficile:
QStringList sl=
{
"\"one\"",
" \" two \"\"\" , \" and a half ",
"three ",
"\t four"
};
for (int i=0; i < sl.size(); ++i)
qDebug() << parseCSV(sl[i]);
Cela correspond au fichier
"one"
" two """ , " and a half
three
<TAB> four
où <TAB> représente le caractère de tabulation; et chaque ligne est introduite dans parseCSV () à son tour. N'écrivez PAS de fichiers .csv comme celui-ci!
Sa sortie est (où qDebug () représente des guillemets dans la chaîne avec \"
et mettre les choses entre guillemets et parens):
("one")
(" two \"", " and a half")
("three")
("four")
Vous pouvez observer que le devis et les espaces supplémentaires ont été conservés à l'intérieur du devis pour l'élément "deux". Dans le cas mal formé pour "et demi", l'espace avant la citation et ceux après le dernier mot ont été supprimés; mais les autres ne l'étaient pas. Les espaces terminaux manquants dans cette routine pourraient être une indication d'une citation de terminal manquante. Les citations dans un champ qui ne commencent ni ne se terminent sont simplement traitées comme faisant partie d'une chaîne. Un devis n'est pas supprimé à la fin d'un champ si l'on ne le démarre pas. Pour détecter une erreur ici, vérifiez simplement un champ qui commence par un devis, mais ne se termine pas par un; et/ou celui qui contient des guillemets mais ne commence et ne se termine pas par un, dans la boucle finale.
Plus que ce qui était nécessaire pour votre cas de test, je sais; mais une réponse générale solide au?, néanmoins - peut-être pour d'autres qui l'ont trouvé.
Adapté de: https://github.com/hnaohiro/qt-csv/blob/master/csv.cpp
Essayez qtcsv bibliothèque pour lire et écrire des fichiers csv. Exemple:
#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;
}
J'ai essayé de le rendre petit et facile à utiliser. Voir le fichier Lisezmoi pour la documentation de la bibliothèque et d'autres exemples de code.
lines = data.split('\n');
puis
for line in lines
column1.add(line.split(',')[0])
Je ne suis pas sûr que la fonction d'ajout existe ou ne pas ajouter à un tableau - appelons la colonne 1