1 /*! 2 A cookbook of examples for CSV reading and writing. 3 4 # List of examples 5 6 This 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) 9 repository. 10 11 For **reading** CSV: 12 13 1. [Basic](#reading-basic) 14 2. [With Serde](#reading-with-serde) 15 3. [Setting a different delimiter](#reading-setting-a-different-delimiter) 16 4. [Without headers](#reading-without-headers) 17 18 For **writing** CSV: 19 20 5. [Basic](#writing-basic) 21 6. [With Serde](#writing-with-serde) 22 23 Please 24 [submit a pull request](https://github.com/BurntSushi/rust-csv/pulls) 25 if you're interested in adding an example to this list! 26 27 # Reading: basic 28 29 This example shows how to read CSV data from stdin and print each record to 30 stdout. 31 32 ```no_run 33 # //cookbook-read-basic.rs 34 use std::{error::Error, io, process}; 35 36 fn 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 48 fn main() { 49 if let Err(err) = example() { 50 println!("error running example: {}", err); 51 process::exit(1); 52 } 53 } 54 ``` 55 56 The 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 66 This is like the previous example, except it shows how to deserialize each 67 record into a struct type that you define. 68 69 For more examples and details on how Serde deserialization works, see the 70 [`Reader::deserialize`](../struct.Reader.html#method.deserialize) 71 method. 72 73 ```no_run 74 # //cookbook-read-serde.rs 75 # #![allow(dead_code)] 76 use std::{error::Error, io, process}; 77 78 use 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)] 83 struct Record { 84 city: String, 85 region: String, 86 country: String, 87 population: Option<u64>, 88 } 89 90 fn 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 101 fn main() { 102 if let Err(err) = example() { 103 println!("error running example: {}", err); 104 process::exit(1); 105 } 106 } 107 ``` 108 109 The 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 119 This example shows how to read CSV data from stdin where fields are separated 120 by `:` instead of `,`. 121 122 ```no_run 123 # //cookbook-read-colon.rs 124 use std::{error::Error, io, process}; 125 126 fn 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 137 fn main() { 138 if let Err(err) = example() { 139 println!("error running example: {}", err); 140 process::exit(1); 141 } 142 } 143 ``` 144 145 The 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 155 The CSV reader in this crate assumes that CSV data has a header record by 156 default, but the setting can be toggled. When enabled, the first record in 157 CSV data in interpreted as the header record and is skipped. When disabled, the 158 first record is not skipped. This example shows how to disable that setting. 159 160 ```no_run 161 # //cookbook-read-no-headers.rs 162 use std::{error::Error, io, process}; 163 164 fn 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 175 fn main() { 176 if let Err(err) = example() { 177 println!("error running example: {}", err); 178 process::exit(1); 179 } 180 } 181 ``` 182 183 The 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 193 This example shows how to write CSV data to stdout. 194 195 ```no_run 196 # //cookbook-write-basic.rs 197 use std::{error::Error, io, process}; 198 199 fn 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 211 fn main() { 212 if let Err(err) = example() { 213 println!("error running example: {}", err); 214 process::exit(1); 215 } 216 } 217 ``` 218 219 The 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 229 This example shows how to write CSV data to stdout with Serde. Namely, we 230 represent each record using a custom struct that we define. In this example, 231 headers are written automatically. 232 233 ```no_run 234 # //cookbook-write-serde.rs 235 use std::{error::Error, io, process}; 236 237 use serde::Serialize; 238 239 #[derive(Debug, Serialize)] 240 struct Record { 241 city: String, 242 region: String, 243 country: String, 244 population: Option<u64>, 245 } 246 247 fn 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 268 fn main() { 269 if let Err(err) = example() { 270 println!("error running example: {}", err); 271 process::exit(1); 272 } 273 } 274 ``` 275 276 The 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 */ 284