C++ 中读取 CSV 文件通常有两种常见的方式:手动解析文件内容或者使用现有的 CSV 解析库。csv-parser 库是一个开源库,用于高效、可靠地解析 CSV 文件。它自动处理包括引用、逗号嵌套、换行符等复杂情况。

1、手动解析 CSV 文件

使用标准 C++ 库(如 fstream)来读取文件并手动解析每一行。这种方法适合简单的 CSV 文件,并且可以根据需要进行自定义。CSVRow 类 用于存储并管理每一行的数据。readNextRow() 方法从输入流中读取一行数据,并根据逗号分割各个字段。

#include <iterator>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <string_view>

class CSVRow
{
public:
    // 按索引访问行中的元素
    std::string_view operator[](std::size_t index) const
    {
        if (index >= m_data.size() - 1) {
            throw std::out_of_range("Index out of range");
        }
        return std::string_view(&m_line[m_data[index] + 1], m_data[index + 1] - (m_data[index] + 1));
    }

    // 返回行中的字段数量
    std::size_t size() const
    {
        return m_data.size() - 1;
    }

    // 从输入流中读取下一行
    void readNextRow(std::istream& str)
    {
        std::getline(str, m_line);  // 读取完整的一行到 m_line

        m_data.clear();
        m_data.emplace_back(-1);  // 从第一个字符的前面开始

        std::string::size_type pos = 0;
        while ((pos = m_line.find(',', pos)) != std::string::npos)
        {
            m_data.emplace_back(pos);  // 存储每个逗号的位置
            ++pos;  // 跳过逗号
        }
        m_data.emplace_back(m_line.size());  // 添加行结束时的位置
    }

private:
    std::string m_line;          // 整行的字符串
    std::vector<std::size_t> m_data;  // 存储逗号和行尾位置的向量
};

// 重载 >> 操作符,从输入流中读取 CSV 行
std::istream& operator>>(std::istream& str, CSVRow& data)
{
    data.readNextRow(str);
    return str;
}

int main()
{
    // 打开 CSV 文件
    std::ifstream file("D:\\1.csv");

    if (!file.is_open()) {
        std::cerr << "Failed to open the file!" << std::endl;
        return 1;
    }

    CSVRow row;
    // 遍历 CSV 文件中的每一行
    while (file >> row)
    {
        // 如果有第 4 个元素(索引 3),则打印它
        if (row.size() > 3) {
            std::cout << "4th Element(" << row[3] << ")\n";
        }
        else {
            std::cout << "Row does not have a 4th element.\n";
        }
    }

    return 0;
}

2、使用第三方 CSV 解析库

CSV 文件包含复杂的格式(如引号内的逗号或换行符),手动解析可能会变得复杂。在这种情况下,可以使用第三方库来处理 CSV 文件。

1)安装 csv-parser

需要安装 csv-parser 库。可以使用以下命令安装,

# 使用 Git 克隆并安装 csv-parser
git clone https://github.com/vincentlaucsb/csv-parser.git
cd csv-parser
make

2)使用csv-parser 库读取 CSV 文件

#include <iostream>
#include <csv.h>  // 引入 csv-parser 库

int main() {
    io::CSVReader<4> in("plop.csv");  // 读取文件,假设文件有 4 列
    in.read_header(io::ignore_extra_column, "Name", "Surname", "Age", "Job");

    std::string name, surname, job;
    int age;
    while (in.read_row(name, surname, age, job)) {  // 逐行读取
        std::cout << "Name: " << name << ", Surname: " << surname
                  << ", Age: " << age << ", Job: " << job << std::endl;
    }

    return 0;
}

推荐文档