Working with CSV in C++: Libraries and Practical Examples
CSV (Comma-Separated Values) is one of the most common formats for storing tabular data. C++ does not have built-in CSV support in the standard library (until C++23), so developers use third-party libraries or write their own parsers. In this article, we will cover the main approaches to working with CSV in C++: from manual parsing to ready-made solutions.
Why are CSV libraries needed?
CSV files seem simple, but in practice they contain many pitfalls:
- Escaping quotes inside fields (e.g.,
"Hello, world") - Multiline values
- Different delimiters (comma, semicolon, tab)
- Different encodings (UTF-8, UTF-16, ANSI)
Ready-made libraries solve these problems and save time.
1. Manual CSV Parsing (without third-party libraries)
For simple cases, you can write a parser yourself. Example of reading CSV using std::ifstream and std::getline:
#include <iostream>#include <fstream>#include <sstream>#include <vector>#include <string>
std::vector<std::vector<std::string>> parseCSV(const std::string& filename) { std::vector<std::vector<std::string>> data; std::ifstream file(filename); std::string line;
while (std::getline(file, line)) { std::vector<std::string> row; std::stringstream ss(line); std::string cell;
while (std::getline(ss, cell, ',')) { // Remove extra quotes (simplified) if (cell.size() >= 2 && cell.front() == '"' && cell.back() == '"') { cell = cell.substr(1, cell.size() - 2); } row.push_back(cell); } data.push_back(row); } return data;}Disadvantages: does not handle escaped commas inside quotes, multiline fields, or empty lines at the end of the file.
2. The libcsv Library (C)
libcsv is a lightweight C library that correctly parses CSV according to RFC 4180. Suitable for projects where performance is important.
Installation (Linux): sudo apt-get install libcsv-dev
#include <csv.h>#include <iostream>#include <vector>
void cb1(void *s, size_t len, void *data) { std::string field(static_cast<char*>(s), len); static_cast<std::vector<std::string>*>(data)->push_back(field);}
void cb2(int c, void *data) { if (c == CsvRowEnd) { // End of row — output auto& row = *static_cast<std::vector<std::string>*>(data); for (const auto& f : row) std::cout << f << " | "; std::cout << ""; row.clear(); }}
int main() { FILE *fp = fopen("data.csv", "r"); if (!fp) return 1;
struct csv_parser p; csv_init(&p, CSV_STRICT);
std::vector<std::string> row; char buf[1024]; size_t bytes_read;
while ((bytes_read = fread(buf, 1, sizeof(buf), fp)) > 0) { csv_parse(&p, buf, bytes_read, cb1, cb2, &row); } csv_fini(&p, cb1, cb2, &row); csv_free(&p); fclose(fp); return 0;}3. The rapidcsv Library (C++ header-only)
rapidcsv is a modern C++17 library that works with header files only. It supports automatic delimiter detection, working with different data types, and CSV writing.
Installation: copy rapidcsv.h into the project.
#include "rapidcsv.h"#include <iostream>#include <vector>
int main() { // Reading CSV rapidcsv::Docum