Travailler avec CSV en C++ : de l'analyse manuelle à la bibliothèque libcsv
Le format CSV (Comma-Separated Values) reste l'un des moyens les plus populaires d'échanger des données tabulaires. En C++, il n'y a pas de support intégré pour CSV, mais il existe plusieurs approches efficaces : l'analyse manuelle à l'aide d'outils standard et des bibliothèques spécialisées comme libcsv. Dans cet article, nous examinerons les deux méthodes, leurs avantages et inconvénients, et fournirons des exemples de code fonctionnels.
Qu'est-ce que CSV et ses particularités
CSV est un format texte où chaque ligne correspond à un enregistrement et les champs sont séparés par des virgules. Les principales difficultés :
- Les champs peuvent contenir des virgules s'ils sont entre guillemets (
"Hello, world") ; - Les guillemets à l'intérieur d'un champ sont échappés par duplication (
"") ; - Le séparateur peut être un autre caractère (point-virgule, tabulation) ;
- Les lignes peuvent contenir des caractères de nouvelle ligne à l'intérieur des guillemets.
Par conséquent, une simple division de la ligne par virgules conduit souvent à des erreurs. Examinons deux méthodes fiables.
Méthode 1 : Analyse manuelle avec std::stringstream
Convient pour les CSV simples sans guillemets imbriqués ni sauts de ligne. L'implémentation se compose de deux fonctions : lecture d'un champ et analyse de la ligne entière.
#include <iostream>#include <fstream>#include <sstream>#include <vector>#include <string>
// Division d'une ligne CSV en champs en tenant compte des guillemetsstd::vector<std::string> parseCSVLine(const std::string& line) { std::vector<std::string> fields; std::string field; bool inQuotes = false;
for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '"' && !inQuotes) { inQuotes = true; } else if (c == '"' && inQuotes) { // Vérification des guillemets échappés if (i + 1 < line.size() && line[i + 1] == '"') { field += '"'; ++i; // sauter le guillemet suivant } else { inQuotes = false; } } else if (c == ',' && !inQuotes) { fields.push_back(field); field.clear(); } else { field += c; } } fields.push_back(field); // dernier champ return fields;}
int main() { std::ifstream file("data.csv"); std::string line;
while (std::getline(file, line)) { auto fields = parseCSVLine(line); for (const auto& f : fields) { std::cout << "[" << f << "] "; } std::cout << std::endl; } return 0;}Avantages : aucune dépendance externe, contrôle total de la logique.
Inconvénients : ne gère pas les champs multilignes (valeur contenant ), nécessite une gestion manuelle des erreurs.
Méthode 2 : Bibliothèque libcsv
libcsv est une bibliothèque C légère pour l'analyse CSV, écrite en C mais fonctionnant parfaitement depuis C++. Elle gère correctement tous les cas standard : guillemets, échappement, champs multilignes, séparateurs personnalisés.
Installation
Téléchargez les sources depuis SourceForge ou installez via un gestionnaire de paquets :
# Linux (Debian/Ubuntu)sudo apt-get install libcsv-dev
# macOSbrew install libcsvExemple de lecture CSV avec libcsv
#include <iostream>#include <fstream>#include <vector>#include <string>#include <cstring>#include <csv.h>
// Structure pour stocker les donnéesstruct CSVData { std::vector<std::vector<std::string>> rows; std::vector<std::string> currentRow;};
// Ca