Working with CSV in C++: From Manual Parsing to the libcsv Library
The CSV (Comma-Separated Values) format remains one of the most popular ways to exchange tabular data. C++ has no built-in CSV support, but there are several effective approaches: manual parsing using standard tools and specialized libraries such as libcsv. In this article, we will cover both methods, their advantages and disadvantages, and provide working code examples.
What is CSV and Its Features
CSV is a text format where each line corresponds to a record, and fields are separated by commas. The main difficulties are:
- Fields can contain commas if they are enclosed in quotes (
"Hello, world"); - Quotes inside a field are escaped by doubling (
""); - The delimiter can be a different character (semicolon, tab);
- Lines can contain newline characters inside quotes.
Therefore, simply splitting a string by commas often leads to errors. Let's look at two reliable methods.
Method 1: Manual Parsing with std::stringstream
Suitable for simple CSV files without nested quotes or line breaks. The implementation consists of two functions: reading a single field and parsing the entire line.
#include <iostream>#include <fstream>#include <sstream>#include <vector>#include <string>
// Splitting a CSV line into fields considering quotesstd::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) { // Check for escaped quotes if (i + 1 < line.size() && line[i + 1] == '"') { field += '"'; ++i; // skip the next quote } else { inQuotes = false; } } else if (c == ',' && !inQuotes) { fields.push_back(field); field.clear(); } else { field += c; } } fields.push_back(field); // last field 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;}Pros: no external dependencies, full control over the logic.
Cons: does not handle multi-line fields (values containing ), requires manual error handling.
Method 2: The libcsv Library
libcsv is a lightweight C library for parsing CSV, written in C but works perfectly from C++. It correctly handles all standard cases: quotes, escaping, multi-line fields, custom delimiters.
Installation
Download the source code from SourceForge or install via a package manager:
# Linux (Debian/Ubuntu)sudo apt-get install libcsv-dev
# macOSbrew install libcsvExample of Reading CSV with libcsv
#include <iostream>#include <fstream>#include <vector>#include <string>#include <cstring>#include <csv.h>
// Structure for storing datastruct CSVData { std::vector<std::vector<std::string>> rows; std::vector<std::string> currentRow;};
// Ca