C++ 怎么读取CSV数据 C++ 解析逗号分隔文本方法【文件流】

7次阅读

最稳妥方式是先用std::getline按行读取再手动切分;需处理引号包围、空字段、UTF-8路径等细节,避免operator>>或逗号分隔误判。

C++ 怎么读取CSV数据 C++ 解析逗号分隔文本方法【文件流】

std::ifstream 逐行读取 csv 最稳妥

CSV 不是标准格式,没有统一规范(比如字段含换行、逗号或引号时需转义),所以别指望一行代码全解析。最可控的方式是先用 std::getline 按行读入字符串,再对每行做字段切分——这样能避免二进制读取错位、编码识别失败等问题。

常见错误:直接用 operator>> 读取,遇到空格或逗号就中断;或用 std::getline(in, line, ',') 试图按逗号分割,但 CSV 的逗号可能在引号内,这会导致字段错位。

实操建议:

  • std::ifstream 打开文件,检查 is_open()failbit
  • 每行用 std::getline(in, line) 读取完整行(保留原始换行和空格)
  • 跳过空行和 bomwindows 记事本生成的 UTF-8 文件开头可能有 xEFxBBxBF
  • 后续再对 line 做安全切分(见下节)

手动切分 CSV 字段要处理引号包围场景

标准 CSV 允许字段用双引号包裹,里面可含逗号、换行甚至双引号(用两个连续双引号表示)。如果只用 std::String::find(',') 粗暴分割,遇到 "Smith, John","25","Engineer" 就会切成 5 段而不是 3 段。

立即学习C++免费学习笔记(深入)”;

实操建议:

  • 写一个简单状态机:记录是否在引号内(in_quotes = false),遇到 " 就翻转状态
  • 只在 !in_quotes && c == ',' 时切分字段
  • 遇到 "" 就替换成单个 "(需在提取字段后做)
  • 字段首尾的引号要去掉,但仅当字段以 " 开头且以 " 结尾时才处理

示例片段(不带引号处理):

std::vector fields; size_t start = 0, end = line.find(','); while (end != std::string::npos) {     fields.push_back(line.substr(start, end - start));     start = end + 1;     end = line.find(',', start); } fields.push_back(line.substr(start)); // 最后一段

std::stringstream 解析数值字段容易出错

读到字符串字段后,常需转成 intdouble 等类型。别直接用 std::stoistd::stod——它们遇到空字符串、纯空格或非法字符会抛 std::invalid_argument,而 CSV 中常见缺失值如 123,,45.6 会产生空字段。

实操建议:

  • 先用 field.empty()field.find_first_not_of(" t") == std::string::npos 判空
  • 转数字前用 std::stringstream ss(field); int x; if (ss >> x && ss.EOF()) { ... },确保整字段都被消费
  • 避免 atoi(field.c_str()),它对空指针或非法输入返回 0,无法区分 “0” 和错误

中文路径或 UTF-8 文件名在 windows 下打不开

Windows 默认用本地编码(如 GBK)解释文件名,而现代编辑器保存的 CSV 多为 UTF-8 编码。用 std::ifstream("数据.csv") 在中文路径下大概率失败(failbit 置位)。

实操建议:

  • linux/macOS 不用额外处理;Windows 下优先改用宽字符接口std::wifstream + std::Filesystem::u8pathc++17)
  • 或用第三方库如 boost::nowide::ifstream
  • 若坚持用窄字符,可先将 UTF-8 路径转为 UTF-16 再调用 _wfopen,但跨平台性差

真正麻烦的不是读取本身,而是 CSV 规范的模糊性:引号嵌套、BOM、混合编码、超长行……这些细节一旦忽略,程序在某个用户文件上静默出错,比崩溃更难排查。

text=ZqhQzanResources