Biblioteca csv para trabalhar com arquivos CSV em Rust
CSV (Comma-Separated Values) — um dos formatos mais comuns para armazenar dados tabulares. Em Rust, para trabalhar com CSV, existe uma biblioteca poderosa, flexível e performática chamada csv, que faz parte do ecossistema BurntSushi (autor do ripgrep e regex). Ela permite ler, escrever, serializar e desserializar dados com mínimo esforço e máxima segurança de tipos.
Instalação
Adicione a dependência no Cargo.toml:
[dependencies]csv = "1.3"Para serialização/desserialização de estruturas, também será necessário o serde:
[dependencies]csv = "1.3"serde = { version = "1.0", features = ["derive"] }Principais funcionalidades da biblioteca
- Leitura e escrita com delimitadores, aspas e caracteres de escape configuráveis.
- Processamento automático de cabeçalhos — trabalho por nomes de colunas.
- Serialização/Desserialização via
serde— conversão de linhas CSV em estruturas Rust fortemente tipadas. - Tratamento flexível de erros — posicionamento de erros (número da linha, coluna).
- Processamento em fluxo — trabalho com arquivos grandes sem carregar tudo na memória.
- Suporte a codificações não UTF-8 (através de crates externos, como
encoding).
Leitura de arquivo CSV
A maneira mais simples de ler um CSV é usar Reader e um iterador sobre os registros.
Exemplo 1: Leitura sem cabeçalhos
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(())}Exemplo 2: Leitura com cabeçalhos
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(())}Usando Serde para tipagem estrita
A maneira mais conveniente é definir uma estrutura anotada com #[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(())}Isso garante que os dados serão automaticamente convertidos para os tipos corretos. Se, por exemplo, no campo age aparecer a string "abc", o programa retornará um erro indicando a linha e a coluna.
Escrita de arquivo CSV
Para escrita, usa-se Writer. É possível escrever tanto linhas brutas quanto estruturas serializadas.
Exemplo: escrita através de estrutura
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