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
Também na biblioteca
Planejador de tarefas em Rust: criando um job scheduler confiável
Geolocalização e Mapas em C# (.NET): Visão Geral de Bibliotecas e Ferramentas
Criptografia em Kotlin: criptografia e hashes
Geração de PDF em Swift (iOS/macOS): UIGraphicsPDFRenderer, PDFKit e Core Graphics