Работа с CSV в C++: библиотеки, парсинг и запись данных

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с CSV в C++: библиотеки и практические примеры

CSV (Comma-Separated Values) — один из самых распространённых форматов для хранения табличных данных. В C++ нет встроенной поддержки CSV в стандартной библиотеке (до C++23), поэтому разработчики используют сторонние библиотеки или пишут собственные парсеры. В этой статье мы разберём основные подходы к работе с CSV в C++: от ручного парсинга до готовых решений.

Зачем нужны библиотеки для CSV?

CSV-файлы кажутся простыми, но на практике содержат много подводных камней:

  • Экранирование кавычек внутри полей (например, "Hello, world")
  • Многострочные значения
  • Разные разделители (запятая, точка с запятой, табуляция)
  • Разные кодировки (UTF-8, UTF-16, ANSI)

Готовые библиотеки решают эти проблемы и экономят время.

1. Ручной парсинг CSV (без сторонних библиотек)

Для простых случаев можно написать парсер самостоятельно. Пример чтения CSV с помощью std::ifstream и 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, ',')) {
            // Удаляем лишние кавычки (упрощённо)
            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;
}

Недостатки: не обрабатывает экранированные запятые внутри кавычек, многострочные поля, пустые строки в конце файла.

2. Библиотека libcsv (C)

libcsv — легковесная библиотека на C, которая корректно парсит CSV в соответствии с RFC 4180. Подходит для проектов, где важна производительность.

Установка (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) {
        // Конец строки — выводим
        auto& row = *static_cast<std::vector<std::string>*>(data);
        for (const auto& f : row) std::cout << f << " | ";
        std::cout << "\n";
        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. Библиотека rapidcsv (C++ header-only)

rapidcsv — современная C++17 библиотека, работающая только с заголовочными файлами. Поддерживает автоматическое определение разделителя, работу с разными типами данных и запись CSV.

Установка: скопировать rapidcsv.h в проект.

#include "rapidcsv.h"
#include <iostream>
#include <vector>

int main() {
    // Чтение CSV
    rapidcsv::Document doc("example.csv");

    // Получить столбец по индексу (все строки)
    std::vector<int> ids = doc.GetColumn<int>(0);
    
    // Получить ячейку по имени столбца и номеру строки
    std::string name = doc.GetCell<std::string>("Name", 2);
    
    // Запись нового CSV
    rapidcsv::Document out;                    

Рекомендаций