J'ai besoin de charger et d'utiliser des données de fichier CSV en C ++. À ce stade, il ne peut s'agir que d'un analyseur délimité par des virgules (c'est-à-dire, ne vous inquiétez pas d'échapper aux nouvelles lignes et virgules). Le besoin principal est un analyseur ligne par ligne qui retournera un vecteur pour la ligne suivante à chaque appel de la méthode.
J'ai trouvé cet article qui semble assez prometteur: http://www.boost.org/doc/libs/1_35_0/libs/spirit/example/fundamental/list_parser.cpp
Je n'ai jamais utilisé Boost's Spirit, mais je suis prêt à l'essayer. Mais seulement s'il n'y a pas de solution plus simple que je néglige.
boost::spirit
analyse. C'est plus pour l'analyse des grammaires que pour l'analyse d'un format de fichier simple. Quelqu'un de mon équipe essayait de l'utiliser pour analyser XML et c'était difficile de déboguer. Éloignez-vousboost::spirit
si possible.spirit
est assez difficile à utiliser pour une bibliothèque de combinateurs d'analyseurs. Ayant eu une expérience (très agréable) avec les(atto)parsec
bibliothèques Haskells , je m'attendais à ce que (l'esprit) fonctionne de manière similaire, mais j'ai abandonné après avoir combattu avec des erreurs de compilation de 600 lignes.Réponses:
Si vous ne vous souciez pas d'échapper à la virgule et à la nouvelle ligne,
ET que vous ne pouvez pas incorporer la virgule et la nouvelle ligne entre guillemets (si vous ne pouvez pas vous échapper alors ...),
alors ce n'est qu'environ trois lignes de code (OK 14 -> Mais sa seulement 15 pour lire l'intégralité du dossier).
Je voudrais simplement créer une classe représentant une ligne.
Puis diffusez dans cet objet:
Mais avec un peu de travail, nous pourrions techniquement créer un itérateur:
la source
istream::operator>>
(comme Eigen), ajoutez uninline
avant la déclaration de l'opérateur pour le corriger.Solution utilisant Boost Tokenizer:
la source
Ma version n'utilise rien d'autre que la bibliothèque C ++ 11 standard. Il s'adapte bien à la citation Excel CSV:
Le code est écrit comme une machine à états finis et consomme un caractère à la fois. Je pense qu'il est plus facile de raisonner.
la source
const char *vinit[] = {""}; vector<string> fields(vinit, end(vinit));
La bibliothèque C ++ String Toolkit (StrTk) possède une classe de grille de jetons qui vous permet de charger des données à partir de fichiers texte, de chaînes ou de tampons de caractères , et de les analyser / les traiter de manière ligne-colonne.
Vous pouvez spécifier les délimiteurs de ligne et les délimiteurs de colonne ou simplement utiliser les valeurs par défaut.
Plus d'exemples peuvent être trouvés ici
la source
options.trim_dquotes = true
supprimant les guillemets environnants (via ), il ne prend pas en charge la suppression des doubles guillemets doubles (par exemple, le champ en"She said ""oh no"", and left."
tant que chaîne c"She said \"oh no\", and left."
). Vous devrez le faire vous-même.strtk
, vous devrez également gérer manuellement les champs entre guillemets doubles qui contiennent des caractères de nouvelle ligne.Vous pouvez utiliser Boost Tokenizer avec escaped_list_separator.
Cela utilise uniquement les fichiers d'en-tête de tokenizer Boost, aucun lien pour booster les bibliothèques requis.
Voici un exemple (voir Parse CSV File With Boost Tokenizer In C ++ pour plus de détails ou
Boost::tokenizer
):la source
Il n'est pas exagéré d'utiliser Spirit pour analyser les CSV. Spirit est bien adapté aux tâches de micro-analyse. Par exemple, avec Spirit 2.1, c'est aussi simple que:
Le vecteur, v, est bourré de valeurs. Il existe une série de didacticiels sur ce sujet dans les nouveaux documents Spirit 2.1 qui viennent d'être publiés avec Boost 1.41.
Le didacticiel passe de simple à complexe. Les analyseurs CSV sont présentés quelque part au milieu et abordent diverses techniques d'utilisation de Spirit. Le code généré est aussi serré que du code manuscrit. Découvrez l'assembleur généré!
la source
Si vous VOULEZ se soucier de l' analyse syntaxique correctement CSV, ce fera ... relativement lentement car il fonctionne un omble chevalier à la fois.
la source
Lors de l'utilisation du Boost Tokenizer escaped_list_separator pour les fichiers CSV, alors il faut être conscient des points suivants:
Le format CSV spécifié par wiki indique que les champs de données peuvent contenir des séparateurs entre guillemets (pris en charge):
Le format CSV spécifié par wiki stipule que les guillemets simples doivent être traités avec des guillemets doubles (escaped_list_separator supprimera tous les caractères de guillemet):
Le format CSV ne spécifie pas que tous les caractères de barre oblique inverse doivent être supprimés (escaped_list_separator supprimera tous les caractères d'échappement).
Une solution de contournement possible pour corriger le comportement par défaut du boost escaped_list_separator:
Cette solution de contournement a pour effet secondaire que les champs de données vides représentés par un guillemet double seront transformés en jeton de guillemet simple. Lors de l'itération à travers les jetons, il faut alors vérifier si le jeton est un guillemet simple et le traiter comme une chaîne vide.
Pas joli mais ça marche, tant qu'il n'y a pas de retour à la ligne dans les guillemets.
la source
Vous voudrez peut-être regarder mon projet FOSS CSVfix ( lien mis à jour ), qui est un éditeur de flux CSV écrit en C ++. L'analyseur CSV n'est pas un prix, mais fait le travail et l'ensemble du package peut faire ce dont vous avez besoin sans avoir à écrire de code.
Voir alib / src / a_csv.cpp pour l'analyseur CSV et csvlib / src / csved_ioman.cpp (
IOManager::ReadCSV
) pour un exemple d'utilisation.la source
Comme toutes les questions CSV semblent être redirigées ici, j'ai pensé publier ma réponse ici. Cette réponse ne répond pas directement à la question du demandeur. Je voulais pouvoir lire dans un flux qui est connu pour être au format CSV, et aussi les types de chaque champ étaient déjà connus. Bien sûr, la méthode ci-dessous peut être utilisée pour traiter chaque champ comme un type de chaîne.
Comme exemple de la façon dont je voulais pouvoir utiliser un flux d'entrée CSV, considérez l'entrée suivante (tirée de la page de wikipedia sur CSV ):
Ensuite, je voulais pouvoir lire les données comme ceci:
C'est la solution que j'ai trouvée.
Avec les assistants suivants qui peuvent être simplifiés par les nouveaux modèles de traits intégraux en C ++ 11:
Essayez-le en ligne!
la source
J'ai écrit un analyseur CSV C ++ 11 uniquement en-tête . Il est bien testé, rapide, prend en charge l'intégralité de la spécification CSV (champs entre guillemets, délimiteur / terminateur entre guillemets, échappement de guillemets, etc.) et est configurable pour tenir compte des CSV qui n'adhèrent pas à la spécification.
La configuration se fait via une interface fluide:
L'analyse n'est qu'une plage basée sur une boucle:
la source
Une autre bibliothèque d'E / S CSV peut être trouvée ici:
http://code.google.com/p/fast-cpp-csv-parser/
la source
Une autre solution similaire à la réponse de Loki Astari , en C ++ 11. Les lignes ici sont des
std::tuple
s d'un type donné. Le code scanne une ligne, puis scanne jusqu'à chaque délimiteur, puis convertit et sauvegarde la valeur directement dans le tuple (avec un peu de code de modèle).Advanges:
std::tuple<t1, ...>
viaoperator>>
.Ce qui manque:
Le code principal:
J'ai mis un petit exemple de travail sur GitHub ; Je l'ai utilisé pour analyser certaines données numériques et il a rempli son rôle.
la source
Voici une autre implémentation d'un analyseur CSV Unicode (fonctionne avec wchar_t). J'en ai écrit une partie, tandis que Jonathan Leffler a écrit le reste.
Remarque: cet analyseur vise à reproduire le comportement d'Excel le plus fidèlement possible, en particulier lors de l'importation de fichiers CSV cassés ou mal formés .
C'est la question d'origine - Analyser un fichier CSV avec des champs multilignes et des guillemets doubles échappés
Il s'agit du code en tant que SSCCE (exemple court, autonome et correct).
la source
J'avais besoin d'une bibliothèque C ++ facile à utiliser pour analyser les fichiers CSV mais je n'en ai trouvé aucune disponible, j'ai donc fini par en créer une. Rapidcsv est une bibliothèque uniquement en-tête C ++ 11 qui donne un accès direct aux colonnes (ou lignes) analysées en tant que vecteurs, dans le type de données de choix. Par exemple:
la source
Excusez-moi, mais tout cela ressemble à beaucoup de syntaxe élaborée pour cacher quelques lignes de code.
Pourquoi pas ça:
la source
",\n"
dans la chaîne?Voici le code pour lire une matrice, notez que vous avez également une fonction csvwrite dans matlab
la source
Vous pouvez ouvrir et lire le fichier .csv à l'aide des fonctions fopen, fscanf, mais l'important est d'analyser les données. La manière la plus simple d'analyser les données à l'aide du délimiteur. Dans le cas de .csv, le délimiteur est ','.
Supposons que votre fichier data1.csv soit le suivant:
vous pouvez symboliser les données et les stocker dans un tableau de caractères, puis utiliser la fonction atoi (), etc. pour les conversions appropriées
[^,], ^ -it inverse la logique, signifie correspondre à n'importe quelle chaîne qui ne contient pas de virgule puis en dernier, dit de faire correspondre la virgule qui a terminé la chaîne précédente.
la source
La première chose que vous devez faire est de vous assurer que le fichier existe. Pour ce faire, il vous suffit d'essayer d'ouvrir le flux de fichiers sur le chemin. Après avoir ouvert le flux de fichiers, utilisez stream.fail () pour voir s'il a fonctionné comme prévu ou non.
Vous devez également vérifier que le fichier fourni est le bon type de fichier. Pour ce faire, vous devez parcourir le chemin de fichier fourni jusqu'à ce que vous trouviez l'extension de fichier. Une fois que vous avez l'extension de fichier, assurez-vous qu'il s'agit d'un fichier .csv.
Cette fonction renverra l'extension de fichier qui sera utilisée plus tard dans un message d'erreur.
Cette fonction appellera en fait les contrôles d'erreur créés ci-dessus, puis analysera le fichier.
la source
Tu dois être fier quand tu utilises quelque chose d'aussi beau que
boost::spirit
Voici ma tentative d'un analyseur (presque) conforme aux spécifications CSV sur ce lien Spécifications CSV (je n'ai pas eu besoin de sauts de ligne dans les champs. Les espaces autour des virgules sont également supprimés).
Après avoir surmonté l'expérience choquante d'attendre 10 secondes pour compiler ce code :), vous pouvez vous asseoir et profiter.
Compiler:
Test (exemple volé sur Wikipedia ):
la source
Cette solution détecte ces 4 cas
la classe complète est à
https://github.com/pedro-vicente/csv-parser
Il lit le fichier caractère par caractère et lit 1 ligne à la fois dans un vecteur (de chaînes), donc adapté aux très gros fichiers.
L'utilisation est
Itérer jusqu'à ce qu'une ligne vide soit renvoyée (fin de fichier). Une ligne est un vecteur où chaque entrée est une colonne CSV.
la déclaration de classe
la mise en oeuvre
la source
Vous pouvez également consulter les capacités de la
Qt
bibliothèque.Il prend en charge les expressions régulières et la classe QString a de belles méthodes, par exemple
split()
renvoyer QStringList, liste des chaînes obtenues en divisant la chaîne d'origine avec un délimiteur fourni. Devrait suffire pour le fichier csv ..Pour obtenir une colonne avec un nom d'en-tête donné, j'utilise ce qui suit: héritage c ++ Qt problème qstring
la source
Si vous ne voulez pas gérer l'inclusion de boost dans votre projet (il est considérablement important si vous ne l'utilisez que pour l'analyse par CSV ...)
J'ai eu de la chance avec l'analyse CSV ici:
http://www.zedwood.com/article/112/cpp-csv-parser
Il gère les champs entre guillemets - mais ne gère pas les caractères en ligne \ n (ce qui est probablement bien pour la plupart des utilisations).
la source
Ceci est un vieux fil mais il est toujours en haut des résultats de recherche, donc j'ajoute ma solution en utilisant std :: stringstream et une méthode de remplacement de chaîne simple par Yves Baumes que j'ai trouvée ici.
L'exemple suivant lira un fichier ligne par ligne, ignorera les lignes de commentaires commençant par // et analysera les autres lignes en une combinaison de chaînes, d'entiers et de doubles. Stringstream effectue l'analyse, mais s'attend à ce que les champs soient délimités par des espaces, donc j'utilise stringreplace pour transformer les virgules en espaces en premier. Il gère les onglets, mais ne traite pas les chaînes entre guillemets.
Les entrées incorrectes ou manquantes sont simplement ignorées, ce qui peut être bon ou non, selon votre situation.
la source
Pour ce que ça vaut, voici mon implémentation. Il traite de l'entrée wstring, mais pourrait être ajusté pour une chaîne facilement. Il ne gère pas la nouvelle ligne dans les champs (comme mon application non plus, mais l'ajout de son support n'est pas trop difficile) et il n'est pas conforme à la fin de ligne "\ r \ n" selon RFC (en supposant que vous utilisez std :: getline), mais il gère correctement la suppression des espaces blancs et les guillemets doubles (espérons-le).
la source
Voici une fonction prête à l'emploi si tout ce dont vous avez besoin est de charger un fichier de données de doubles (pas d'entiers, pas de texte).
la source
Un autre moyen rapide et facile consiste à utiliser
Boost.Fusion I/O
:Les sorties:
la source
J'ai écrit une belle façon d'analyser les fichiers CSV et j'ai pensé que je devrais l'ajouter comme réponse:
la source
Il est possible d'utiliser
std::regex
.Selon la taille de votre fichier et la mémoire dont vous disposez, il est possible de le lire ligne par ligne ou entièrement dans un fichier
std::string
.Pour lire le fichier, on peut utiliser:
alors vous pouvez faire correspondre ce qui est en fait personnalisable à vos besoins.
la source
Comme je n'ai pas l'habitude de booster pour le moment, je proposerai une solution plus simple. Supposons que votre fichier .csv comporte 100 lignes avec 10 numéros dans chaque ligne séparés par un «,». Vous pouvez charger ces données sous la forme d'un tableau avec le code suivant:
la source