Trabalhando com CSV em Rust: bibliotecas csv, serde e processamento eficiente de dados

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Trabalhando com CSV em Rust: bibliotecas, exemplos de código e melhores práticas



CSV (Comma-Separated Values) — um dos formatos mais comuns para armazenar dados tabulares. No ecossistema Rust, existe uma biblioteca poderosa e flexível chamada csv, que, combinada com o crate serde, permite ler, escrever e transformar dados CSV de forma conveniente. Neste artigo, abordaremos detalhadamente como trabalhar com CSV em Rust, desde o parsing básico até a serialização de estruturas complexas.



Instalação e configuração de dependências



Para começar, adicione as seguintes dependências ao arquivo Cargo.toml:



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


A biblioteca csv fornece uma API de baixo nível para leitura e escrita, enquanto o serde oferece desserialização automática de linhas CSV para estruturas Rust.



Leitura de arquivo CSV linha por linha



A maneira mais simples de ler um CSV é usar o Reader do crate csv. Vejamos um exemplo com o arquivo users.csv:



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

fn main() -> Result<(), Box<dyn Error>> { let mut rdr = Reader::from_path("users.csv")?;

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


Este código exibe cada linha como um vetor de strings StringRecord. No entanto, na prática, é mais comum trabalhar com dados tipados.



Desserialização em estruturas com serde



Vamos declarar uma estrutura que corresponde às colunas do CSV:



use serde::Deserialize;

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


Agora podemos ler os registros diretamente em instâncias de User:



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

fn main() -> Result<(), Box<dyn Error>> { let mut rdr = Reader::from_path("users.csv")?;

for result in rdr.deserialize() { let user: User = result?; println!("{} ({} anos) de {}", user.name, user.age, user.city); } Ok(())}


A biblioteca mapeia automaticamente os cabeçalhos do CSV para os campos da estrutura. Se a ordem ou os nomes das colunas forem diferentes, use o atributo #[serde(rename = "...")].



Escrita de arquivo CSV



A criação de um arquivo CSV é feita com o Writer. Escrita de dados estruturados via serde:



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

#[derive(Debug, Serialize)]struct Product { id: u32, name: String, price: f64,}

fn main() -> Result<(), Box<dyn Error>> { let mut wtr = Writer::from_path("products.csv")?;

let products = vec![ Product { id: 1, name: "Notebook".into(), price: 75000.0 }, Product { id: 2, name: "Mouse".into(), price: 1500.0 }, ];

for product in &products { wtr.serialize(product)?; }

wtr.flush()?; println!("Arquivo products.csv escrito com sucesso"); Ok(())}


Observe: o Writer adiciona automaticamente os cabeçalhos com base nos nomes dos campos da estrutura.



Configuração de delimitadores e aspas



Por padrão, são usados vírgula e aspas duplas. Se o seu arquivo usar ponto e vírgula (por exemplo, em localidades europeias), configure o ReaderBuilder:



use csv::ReaderBuilder;

let mut rdr = ReaderBuilder::new() .delimiter(b';') .has_headers(true) .from_path("data.tsv")?;


Da mesma forma, o WriterBuilder pode ser configurado para escrita.



Tratamento de erros e dados inválidos



Recommendations