使用 C++ 进行 CSV 文件管理

2025年03月22日 | 阅读 10 分钟

在本文中,我们将使用 C++ 讨论 CSV 文件管理,包括其特性、用途和几个示例。

什么是 CSV?

逗号分隔值 (CSV) 是一种基本的文件格式,用于在数据库和电子表格中存储表格数据。CSV 文件包含纯文本,值之间用逗号分隔,每行代表一行数据。

CSV 格式的一些关键特性包括

  • 纯文本格式: CSV 文件仅包含 ASCII 字符,这使其具有普遍的可读性。
  • 逗号分隔值: 每行中的每个字段或值都用逗号(或其他分隔符,如制表符或管道符)分隔。
  • 第一行通常包含标题值: 第一行通常包含列名来表示元数据。
  • 文字值需要加引号: 任何包含逗号、换行符或引号的值都必须用双引号括起来。
  • 解释的数据类型: 由于 CSV 没有数据模式,所有数据类型都必须推断。
  • 跨平台可移植性: CSV 可以在程序和平台之间轻松交换表格数据。
  • 文件大小紧凑: 没有笨重的语法或标签,与 XML 或其他格式相比,文件更小。

为什么使用 CSV 文件?

以下是 CSV(逗号分隔值)文件常用的主要原因:

  1. 简单性: CSV 是一种非常简单的文件格式,易于理解和使用。与其他数据文件相比,它需要的格式化最少。
  2. 可移植性: 几乎任何应用程序都可以打开 CSV 文件。它与许多数据库、电子表格、编程语言等兼容。这使得数据交换变得容易。
  3. 可编辑性: 基本文本编辑器可以轻松手动查看和编辑 CSV 数据。这对于管理小型数据集很有用。
  4. 大小: CSV 文件的结构使其比其他数据格式更轻便紧凑。易于传输和存储。
  5. 容量: CSV 可以有效地处理包含数百万行的超大数据集,而 Excel 等程序在此类数据集上会受限于大小。
  6. 导出: 许多程序都包含将表格数据导出为 CSV 格式的内置选项,以便于互操作。
  7. 导入: 同时,CSV 数据可以轻松导入各种分析工具、电子表格程序和数据库进行分析。
  8. 简洁: CSV 专注于数据,不包含元数据冗余,从而节省空间。

使用 C++ 管理 CSV 文件中的记录

CSV(逗号分隔值) 文件是存储和交换表格数据的流行格式。虽然 CSV 文件很简单,但从 C++ 程序管理这些记录需要一些技巧。在这里,我们介绍用于安全地添加、更新和删除 CSV 记录的函数。

打开 CSV 文件

我们首先需要使用 C++ 的 ifstream 打开 CSV 文件,并解析其内容以进行读取和写入。我们可以使用 C++ 的 std::getline() 来读取每一行。像 CSV.h 这样的 CSV 解析库可以简化逗号分隔字段的分离。

  • 打开 CSV 文件进行读取
  • 打开 CSV 文件进行写入
  • 打开 CSV 文件以进行读取和写入

需要记住的关键点

  • 使用 ifstream 打开文件以进行输入读取。
  • 使用 ofstream 打开文件以进行输出写入。
  • 使用 fstream 以读/写模式打开。
  • 将文件名用双引号作为参数传递。
  • 对于 fstream,指定 ios::inios::out 访问模式。

创建操作

使用 创建操作,我们可以向现有的 CSV 文件添加新记录(行)。

例如,考虑一个 CSV 文件 'data.csv',其内容如下:

如果要添加新记录,请遵循以下步骤:

  1. 使用输入 文件流 打开 CSV 文件并将其解析成行。
  2. 创建新行作为字符串向量。
  3. 将此新行附加到行向量。
  4. 最后,将更新后的行保存回 CSV 文件。

示例

让我们以一个示例来说明使用 创建 方法的 CSV 文件 操作。

输出

Name, Age, City
John,30, New York  
Sarah,28, Miami
Sam,35, Boston

读取特定记录

要在 C++ 中从 CSV 文件读取记录,请使用 ifstream 打开文件,然后读取每一行并使用 istringstream 提取所需的字段。比较值以查找感兴趣的记录。如果找到记录,则处理或打印该记录。执行完毕后,关闭文件。

示例

让我们以一个示例来说明使用 读取 方法的 CSV 文件 操作。

输出

Record found: Alice 30 London

写入 CSV 文件

在 C++ 中,创建 ofstream 对象 并以写入模式打开文件以写入 CSV 文件。利用 << 运算符 写入数据,确保值用逗号分隔以区分列。使用 close() 方法完成进程,关闭文件。这是一个展示其工作原理的简短代码。

示例

输出

Name, Age, City,
John,25, New York,
Alice,30, London,
Bob,22, Paris,

更新记录

这是更新 CSV 文件中记录的一种方法:

  1. 打开 CSV 文件。
  2. 请逐行读取 CSV 文件 的所有内容并将其存储在内存中。这会创建一个可供我们操作的 CSV 数据表示。
  3. 扫描加载的 CSV 数据以查找我们想要更新的 行/记录。根据唯一的标识符(如 ID 列或姓名)来识别它。
  4. 找到目标行后,更新所需的列值。例如,更新电话号码或电子邮件地址字段。
  5. 用内存中的修改数据(包括更新的行)完全覆盖现有的 CSV 文件。现在,所有内容都将与更新后的数据匹配。

示例

让我们以一个示例来说明使用 更新 方法的 CSV 文件 操作。

输出

更新 Alice 的记录为年龄 32 岁,城市 “曼彻斯特” 后的输出将是:

Name, Age, City
John,25, New York
Alice,32, Manchester
Bob,22, Paris

删除记录

以下是删除 CSV 文件中记录的简单步骤:

  1. 打开 CSV 文件并将内容读取到数据结构中(例如,向量的向量)。
  2. 在数据中搜索以识别要删除的记录。
  3. 从数据结构中删除记录。
  4. 然后,以写入模式打开 CSV 文件。
  5. 将数据结构中的更新数据写回 CSV 文件。
  6. 关闭文件。

要理解的主要几点:

  1. 将 CSV 文件加载到内存中以便于操作。
  2. 将更新后的内存结构写回 CSV 文件。

示例

让我们以一个示例来说明使用 删除 方法的 CSV 文件 操作。

在此代码中:

  • CSV 文件被读入二维向量
  • 用户提供要删除的记录的索引。
  • 向量的 'erase()' 函数会删除该记录。
  • 更新后的向量被写回 CSV 文件。

输出

删除前

Name, Age, City
John,25, New York
Alice,30, London
Bob,22, Paris

删除 CSV 文件中 Alice 的记录后

Name, Age, City
John,25, New York
Bob,22, Paris

优化大型 CSV 文件处理

以下是在 C++ 中处理大型 CSV 文件时优化性能的一些方法:

1. 缓冲 I/O

  • 使用 'fstream' 等缓冲流而不是无缓冲输入/输出。
  • 缓冲减少了系统调用的次数,提高了磁盘 I/O 效率。

2. 并行处理

  • 使用标准并行算法通过多个线程处理 CSV 文件。
  • 每个线程独立处理一部分行。
  • 合并来自线程的输出。
  • 并行利用多核架构。

3. 压缩

  • 写入 CSV 时使用 gzip 等压缩算法。
  • 压缩大小可减少 I/O 时间。
  • 利用多核硬件加速的压缩库。

4. 数据格式化

  • 为解析后的 CSV 数据预先分配向量大小,而不是动态增长。
  • 使用 reserve() 容量以尽量减少重新分配。
  • 可变长度数据(如字符串)会增加解析开销。

5. 其他要点

  • 使用内存映射文件进行随机访问,无需解析。
  • 分批数据库插入,将多行一起插入。
  • 性能分析以识别瓶颈 - I/O、解析、处理。

结合缓冲、压缩、并行处理以及减少分配/副本可以显著加快大型 CSV 处理速度。

处理 CSV 文件时的异常和错误处理

以下是处理 CSV 文件错误和异常的关键策略:

常见错误和异常

文件未找到

  • 打开文件前检查文件是否存在。
  • 如果未找到,请提供信息性错误消息。

无效格式

  • 使用 try...except 块来捕获解析错误。
  • 验证文件结构和数据类型。
  • 考虑使用可以处理常见格式问题的库。

数据错误

  • 验证数据类型和范围。
  • 妥善处理缺失或不一致的值(例如,用默认值填充,标记以便审查)。

权限问题

  • 确保您的程序具有必要的读/写权限。

编码错误

  • 打开文件时指定正确的编码(例如,UTF-8)。

最佳实践

使用 try...except 块:

  • 将文件打开和操作放在 try...except 块中,以优雅地处理潜在错误。

提供信息性错误消息

  • 包含清晰的错误消息,并为用户或开发人员提供有用的上下文。

验证数据

  • 检查有效的数据类型、范围和一致性。

记录错误

  • 记录错误以进行调试和监控。

考虑数据验证库

  • 使用 pandascsvlint 等库进行高级验证和错误处理。

彻底测试

  • 使用各种输入文件(包括可能包含错误的文件)测试代码,以确保其健壮性。

示例

输出

Name Age City 
John 25 New York 
Alice 30 London 
Bob 22 Paris

附加提示

  • 编写健壮的代码: 预见潜在的错误,并设计代码以优雅地处理它们。
  • 考虑用户体验: 提供清晰的反馈,并指导用户解决错误。
  • 使用合适的数据结构: 选择与 CSV 数据匹配的结构,以实现高效处理和错误处理。