Arbeiten mit CSV in C++: Vom manuellen Parsen bis zur Bibliothek libcsv
Das CSV-Format (Comma-Separated Values) bleibt eine der beliebtesten Methoden zum Austausch von Tabellendaten. In C++ gibt es keine integrierte Unterstützung für CSV, aber es gibt mehrere effiziente Ansätze: manuelles Parsen mit Standardmitteln und spezialisierte Bibliotheken wie libcsv. In diesem Artikel werden wir beide Methoden, ihre Vor- und Nachteile sowie funktionierende Codebeispiele besprechen.
Was ist CSV und seine Besonderheiten
CSV ist ein Textformat, bei dem jede Zeile einem Datensatz entspricht und die Felder durch Kommas getrennt werden. Die Hauptschwierigkeiten:
- Felder können Kommas enthalten, wenn sie in Anführungszeichen gesetzt sind (
"Hallo, Welt"); - Anführungszeichen innerhalb eines Feldes werden durch Verdopplung maskiert (
""); - Das Trennzeichen kann ein anderes Zeichen sein (Semikolon, Tabulator);
- Zeilen können innerhalb von Anführungszeichen Zeilenumbrüche enthalten.
Daher führt das einfache Aufteilen einer Zeile nach Kommas oft zu Fehlern. Betrachten wir zwei zuverlässige Methoden.
Methode 1: Manuelles Parsen mit std::stringstream
Geeignet für einfache CSVs ohne verschachtelte Anführungszeichen und Zeilenumbrüche. Die Implementierung besteht aus zwei Funktionen: Lesen eines einzelnen Feldes und Parsen der gesamten Zeile.
#include <iostream>#include <fstream>#include <sstream>#include <vector>#include <string>
// Aufteilen einer CSV-Zeile in Felder unter Berücksichtigung von Anführungszeichenstd::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) { // Prüfung auf maskierte Anführungszeichen if (i + 1 < line.size() && line[i + 1] == '"') { field += '"'; ++i; // nächstes Anführungszeichen überspringen } else { inQuotes = false; } } else if (c == ',' && !inQuotes) { fields.push_back(field); field.clear(); } else { field += c; } } fields.push_back(field); // letztes Feld 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;}Vorteile: Keine externen Abhängigkeiten, volle Kontrolle über die Logik.
Nachteile: Verarbeitet keine mehrzeiligen Felder (Wert, der enthält), erfordert manuelle Fehlerbehandlung.
Methode 2: Die Bibliothek libcsv
libcsv ist eine leichtgewichtige C-Bibliothek zum Parsen von CSV, die in C geschrieben ist, aber hervorragend aus C++ verwendet werden kann. Sie verarbeitet korrekt alle Standardfälle: Anführungszeichen, Maskierung, mehrzeilige Felder, benutzerdefinierte Trennzeichen.
Installation
Laden Sie die Quellen von SourceForge herunter oder installieren Sie sie über den Paketmanager:
# Linux (Debian/Ubuntu)sudo apt-get install libcsv-dev
# macOSbrew install libcsvBeispiel zum Lesen von CSV mit libcsv
#include <iostream>#include <fstream>#include <vector>#include <string>#include <cstring>#include <csv.h>
// Struktur zum Speichern der Datenstruct CSVData { std::vector<std::vector<std::string>> rows; std::vector<std::string> currentRow;};
// Ca Auch in der Bibliothek
Kryptographie in Go (Golang): Verschlüsselung und Hashing
Caching in Go (Golang): Redis und alternative Tools
Arbeiten mit Excel in Rust: Bibliotheken und Codebeispiele
Arbeiten mit YAML in JavaScript (Node.js): Parsing, Generierung und Validierung
Swift-Aufgabenplaner: GCD, OperationQueue und Combine für iOS/macOS