在Rust中处理CSV:csv库与实战示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

用于处理CSV文件的Rust库:csv



CSV(逗号分隔值)是存储表格数据最常用的格式之一。在Rust中,有一个强大、灵活且高性能的库csv用于处理CSV,它是BurntSushi(ripgrep和regex的作者)生态系统的一部分。它允许以最小的代价和最大的类型安全性来读取、写入、序列化和反序列化数据。



安装

在Cargo.toml中添加依赖:

[dependencies]csv = "1.3"


对于结构的序列化/反序列化,还需要serde:

[dependencies]csv = "1.3"serde = { version = "1.0", features = ["derive"] }


库的主要功能

  • 读取和写入,支持自定义分隔符、引号和转义字符。
  • 自动处理表头——按列名操作。
  • 通过serde进行序列化/反序列化——将CSV行转换为强类型的Rust结构。
  • 灵活的错误处理——错误定位(行号、列号)。
  • 流式处理——处理大文件而无需全部加载到内存。
  • 支持非UTF-8编码(通过外部crate,例如encoding)。


读取CSV文件

读取CSV最简单的方法是使用Reader和记录迭代器。



示例1:无表头读取

use csv::ReaderBuilder;use std::error::Error;

fn read_csv_no_headers() -> Result<(), Box<dyn Error>> { let data = "name,age,cityAlice,30,LondonBob,25,Paris"; let mut reader = ReaderBuilder::new() .has_headers(false) .from_reader(data.as_bytes());

for result in reader.records() { let record = result?; println!("{:?}", record); } Ok(())}


示例2:有表头读取

use csv::Reader;use std::error::Error;

fn read_csv_with_headers() -> Result<(), Box<dyn Error>> { let data = "name,age,cityAlice,30,LondonBob,25,Paris"; let mut reader = Reader::from_reader(data.as_bytes());

for result in reader.deserialize() { let record: (String, u32, String) = result?; println!("{} is {} years old from {}", record.0, record.1, record.2); } Ok(())}


使用Serde进行强类型化

最方便的方法是定义一个带有#[derive(Deserialize)]注解的结构。



use serde::Deserialize;use csv::Reader;use std::error::Error;

#[derive(Debug, Deserialize)]struct Person { name: String, age: u32, city: String,}

fn read_typed_csv() -> Result<(), Box<dyn Error>> { let data = "name,age,cityAlice,30,LondonBob,25,Paris"; let mut reader = Reader::from_reader(data.as_bytes());

for result in reader.deserialize() { let person: Person = result?; println!("{:?}", person); } Ok(())}


这保证了数据会自动转换为所需的类型。例如,如果age字段中出现了字符串"abc",程序将返回错误,并指明行和列。



写入CSV文件

写入使用Writer。可以写入原始字符串,也可以写入序列化后的结构。



示例:通过结构写入

use serde::Serialize;use csv::Writer;use std::error::Error;

#[derive(Debug, Serialize)]struct Person { name: String, age: u32, city: String,}

fn write_csv() -> Result<(), Box<dyn

推荐