CSV processing
Read CSV records
Reads standard CSV records into csv::StringRecord
— a weakly typed
data representation which expects valid UTF-8 rows. Alternatively,
csv::ByteRecord
makes no assumptions about UTF-8.
use csv::Error;
fn main() -> Result<(), Error> {
let csv = "year,make,model,description
1948,Porsche,356,Luxury sports car
1967,Ford,Mustang fastback 1967,American car";
let mut reader = csv::Reader::from_reader(csv.as_bytes());
for record in reader.records() {
let record = record?;
println!(
"In {}, {} built the {} model. It is a {}.",
&record[0],
&record[1],
&record[2],
&record[3]
);
}
Ok(())
}
Serde deserializes data into strongly type structures. See the
csv::Reader::deserialize
method.
use serde::Deserialize;
#[derive(Deserialize)]
struct Record {
year: u16,
make: String,
model: String,
description: String,
}
fn main() -> Result<(), csv::Error> {
let csv = "year,make,model,description
1948,Porsche,356,Luxury sports car
1967,Ford,Mustang fastback 1967,American car";
let mut reader = csv::Reader::from_reader(csv.as_bytes());
for record in reader.deserialize() {
let record: Record = record?;
println!(
"In {}, {} built the {} model. It is a {}.",
record.year,
record.make,
record.model,
record.description
);
}
Ok(())
}
Read CSV records with different delimiter
Reads CSV records with a tab delimiter
.
use csv::Error;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Record {
name: String,
place: String,
#[serde(deserialize_with = "csv::invalid_option")]
id: Option<u64>,
}
use csv::ReaderBuilder;
fn main() -> Result<(), Error> {
let data = "name\tplace\tid
Mark\tMelbourne\t46
Ashley\tZurich\t92";
let mut reader = ReaderBuilder::new().delimiter(b'\t').from_reader(data.as_bytes());
for result in reader.deserialize::<Record>() {
println!("{:?}", result?);
}
Ok(())
}
Filter CSV records matching a predicate
Returns only the rows from data
with a field that matches query
.
Disclaimer: this example has been adapted from the csv crate tutorial.
Handle invalid CSV data with Serde
CSV files often contain invalid data. For these cases, the csv
crate
provides a custom deserializer, csv::invalid_option
, which automatically
converts invalid data to None values.
use csv::Error;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Record {
name: String,
place: String,
#[serde(deserialize_with = "csv::invalid_option")]
id: Option<u64>,
}
fn main() -> Result<(), Error> {
let data = "name,place,id
mark,sydney,46.5
ashley,zurich,92
akshat,delhi,37
alisha,colombo,xyz";
let mut rdr = csv::Reader::from_reader(data.as_bytes());
for result in rdr.deserialize() {
let record: Record = result?;
println!("{:?}", record);
}
Ok(())
}
Serialize records to CSV
This example shows how to serialize a Rust tuple. csv::writer
supports automatic
serialization from Rust types into CSV records. write_record
writes
a simple record containing string data only. Data with more complex values
such as numbers, floats, and options use serialize
. Since CSV
writer uses internal buffer, always explicitly flush
when done.
Serialize records to CSV using Serde
The following example shows how to serialize custom structs as CSV records using the serde crate.
Transform CSV column
Transform a CSV file containing a color name and a hex color into one with a color name and an rgb color. Utilizes the csv crate to read and write the csv file, and serde to deserialize and serialize the rows to and from bytes.
See csv::Reader::deserialize
, serde::Deserialize
, and std::str::FromStr