csv/cookbook.rs
1/*!
2A cookbook of examples for CSV reading and writing.
3
4# List of examples
5
6This is a list of examples that follow. Each of them can be found in the
7`examples` directory of the
8[`rust-csv`](https://github.com/BurntSushi/rust-csv)
9repository.
10
11For **reading** CSV:
12
131. [Basic](#reading-basic)
142. [With Serde](#reading-with-serde)
153. [Setting a different delimiter](#reading-setting-a-different-delimiter)
164. [Without headers](#reading-without-headers)
17
18For **writing** CSV:
19
205. [Basic](#writing-basic)
216. [With Serde](#writing-with-serde)
22
23Please
24[submit a pull request](https://github.com/BurntSushi/rust-csv/pulls)
25if you're interested in adding an example to this list!
26
27# Reading: basic
28
29This example shows how to read CSV data from stdin and print each record to
30stdout.
31
32```no_run
33# //cookbook-read-basic.rs
34use std::{error::Error, io, process};
35
36fn example() -> Result<(), Box<dyn Error>> {
37 // Build the CSV reader and iterate over each record.
38 let mut rdr = csv::Reader::from_reader(io::stdin());
39 for result in rdr.records() {
40 // The iterator yields Result<StringRecord, Error>, so we check the
41 // error here..
42 let record = result?;
43 println!("{:?}", record);
44 }
45 Ok(())
46}
47
48fn main() {
49 if let Err(err) = example() {
50 println!("error running example: {}", err);
51 process::exit(1);
52 }
53}
54```
55
56The above example can be run like so:
57
58```ignore
59$ git clone git://github.com/BurntSushi/rust-csv
60$ cd rust-csv
61$ cargo run --example cookbook-read-basic < examples/data/smallpop.csv
62```
63
64# Reading: with Serde
65
66This is like the previous example, except it shows how to deserialize each
67record into a struct type that you define.
68
69For more examples and details on how Serde deserialization works, see the
70[`Reader::deserialize`](../struct.Reader.html#method.deserialize)
71method.
72
73```no_run
74# //cookbook-read-serde.rs
75# #![allow(dead_code)]
76use std::{error::Error, io, process};
77
78use serde::Deserialize;
79
80// By default, struct field names are deserialized based on the position of
81// a corresponding field in the CSV data's header record.
82#[derive(Debug, Deserialize)]
83struct Record {
84 city: String,
85 region: String,
86 country: String,
87 population: Option<u64>,
88}
89
90fn example() -> Result<(), Box<dyn Error>> {
91 let mut rdr = csv::Reader::from_reader(io::stdin());
92 for result in rdr.deserialize() {
93 // Notice that we need to provide a type hint for automatic
94 // deserialization.
95 let record: Record = result?;
96 println!("{:?}", record);
97 }
98 Ok(())
99}
100
101fn main() {
102 if let Err(err) = example() {
103 println!("error running example: {}", err);
104 process::exit(1);
105 }
106}
107```
108
109The above example can be run like so:
110
111```ignore
112$ git clone git://github.com/BurntSushi/rust-csv
113$ cd rust-csv
114$ cargo run --example cookbook-read-serde < examples/data/smallpop.csv
115```
116
117# Reading: setting a different delimiter
118
119This example shows how to read CSV data from stdin where fields are separated
120by `:` instead of `,`.
121
122```no_run
123# //cookbook-read-colon.rs
124use std::{error::Error, io, process};
125
126fn example() -> Result<(), Box<dyn Error>> {
127 let mut rdr = csv::ReaderBuilder::new()
128 .delimiter(b':')
129 .from_reader(io::stdin());
130 for result in rdr.records() {
131 let record = result?;
132 println!("{:?}", record);
133 }
134 Ok(())
135}
136
137fn main() {
138 if let Err(err) = example() {
139 println!("error running example: {}", err);
140 process::exit(1);
141 }
142}
143```
144
145The above example can be run like so:
146
147```ignore
148$ git clone git://github.com/BurntSushi/rust-csv
149$ cd rust-csv
150$ cargo run --example cookbook-read-colon < examples/data/smallpop-colon.csv
151```
152
153# Reading: without headers
154
155The CSV reader in this crate assumes that CSV data has a header record by
156default, but the setting can be toggled. When enabled, the first record in
157CSV data in interpreted as the header record and is skipped. When disabled, the
158first record is not skipped. This example shows how to disable that setting.
159
160```no_run
161# //cookbook-read-no-headers.rs
162use std::{error::Error, io, process};
163
164fn example() -> Result<(), Box<dyn Error>> {
165 let mut rdr = csv::ReaderBuilder::new()
166 .has_headers(false)
167 .from_reader(io::stdin());
168 for result in rdr.records() {
169 let record = result?;
170 println!("{:?}", record);
171 }
172 Ok(())
173}
174
175fn main() {
176 if let Err(err) = example() {
177 println!("error running example: {}", err);
178 process::exit(1);
179 }
180}
181```
182
183The above example can be run like so:
184
185```ignore
186$ git clone git://github.com/BurntSushi/rust-csv
187$ cd rust-csv
188$ cargo run --example cookbook-read-no-headers < examples/data/smallpop-no-headers.csv
189```
190
191# Writing: basic
192
193This example shows how to write CSV data to stdout.
194
195```no_run
196# //cookbook-write-basic.rs
197use std::{error::Error, io, process};
198
199fn example() -> Result<(), Box<dyn Error>> {
200 let mut wtr = csv::Writer::from_writer(io::stdout());
201
202 // When writing records without Serde, the header record is written just
203 // like any other record.
204 wtr.write_record(&["city", "region", "country", "population"])?;
205 wtr.write_record(&["Southborough", "MA", "United States", "9686"])?;
206 wtr.write_record(&["Northbridge", "MA", "United States", "14061"])?;
207 wtr.flush()?;
208 Ok(())
209}
210
211fn main() {
212 if let Err(err) = example() {
213 println!("error running example: {}", err);
214 process::exit(1);
215 }
216}
217```
218
219The above example can be run like so:
220
221```ignore
222$ git clone git://github.com/BurntSushi/rust-csv
223$ cd rust-csv
224$ cargo run --example cookbook-write-basic > /tmp/simplepop.csv
225```
226
227# Writing: with Serde
228
229This example shows how to write CSV data to stdout with Serde. Namely, we
230represent each record using a custom struct that we define. In this example,
231headers are written automatically.
232
233```no_run
234# //cookbook-write-serde.rs
235use std::{error::Error, io, process};
236
237use serde::Serialize;
238
239#[derive(Debug, Serialize)]
240struct Record {
241 city: String,
242 region: String,
243 country: String,
244 population: Option<u64>,
245}
246
247fn example() -> Result<(), Box<dyn Error>> {
248 let mut wtr = csv::Writer::from_writer(io::stdout());
249
250 // When writing records with Serde using structs, the header row is written
251 // automatically.
252 wtr.serialize(Record {
253 city: "Southborough".to_string(),
254 region: "MA".to_string(),
255 country: "United States".to_string(),
256 population: Some(9686),
257 })?;
258 wtr.serialize(Record {
259 city: "Northbridge".to_string(),
260 region: "MA".to_string(),
261 country: "United States".to_string(),
262 population: Some(14061),
263 })?;
264 wtr.flush()?;
265 Ok(())
266}
267
268fn main() {
269 if let Err(err) = example() {
270 println!("error running example: {}", err);
271 process::exit(1);
272 }
273}
274```
275
276The above example can be run like so:
277
278```ignore
279$ git clone git://github.com/BurntSushi/rust-csv
280$ cd rust-csv
281$ cargo run --example cookbook-write-serde > /tmp/simplepop.csv
282```
283*/