CSV in Rust
Use case
You need to read or write CSV data: exports, imports, reports, or any tabular data. The csv crate with serde gives type-safe, header-aware CSV handling.
In C#: Like CsvHelper, or manual parsing with TextFieldParser / string split. In Rust, csv + serde map rows to structs.
Reading CSV with serde
Define a struct that matches your columns and derive Deserialize. Use csv::Reader to read from a file or string.
use csv::Reader;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Record {
name: String,
age: u32,
city: String,
}
let mut rdr = Reader::from_path("data.csv")?;
for result in rdr.deserialize() {
let record: Record = result?;
println!("{:?}", record);
}In C#: Like mapping each row to a class with CsvHelper. Column names (or indices) map to struct fields; use #[serde(rename = "Column Name")] if headers differ.
Writing CSV
Use csv::Writer and serialize (or serde::Serialize on a struct) to write rows.
use csv::Writer;
use serde::Serialize;
#[derive(Serialize)]
struct Row {
id: u32,
name: String,
}
let mut wtr = Writer::from_path("out.csv")?;
// `serialize` writes the header row automatically from the struct's field
// names (it's enabled by default). Don't also call `write_record` for the
// header, or it will be written twice.
wtr.serialize(Row { id: 1, name: "Alice".into() })?;
wtr.flush()?;In C#: Like writing headers then serializing objects to CSV rows. Here the
header comes for free from the field names. If you ever need to write rows with
no header, configure a WriterBuilder with .has_headers(false).
Headers and byte records
reader.headers()?– get the header row as a string record.reader.byte_records()– read raw byte records (no serde) for speed or custom parsing.Writer::from_writer(std::io::stdout())– write to stdout (e.g. for pipelines).
Key takeaway
Use the csv crate with Reader::from_path / Writer::from_path. Derive Deserialize/Serialize with serde to map rows to structs. Handle Result on each row when deserializing.