Struct csv::Writer [] [src]

pub struct Writer<W: Write> { /* fields omitted */ }

A already configured CSV writer.

A CSV writer takes as input Rust values and writes those values in a valid CSV format as output.

While CSV writing is considerably easier than parsing CSV, a proper writer will do a number of things for you:

  1. Quote fields when necessary.
  2. Check that all records have the same number of fields.
  3. Write records with a single empty field correctly.
  4. Automatically serialize normal Rust types to CSV records. When that type is a struct, a header row is automatically written corresponding to the fields of that struct.
  5. Use buffering intelligently and otherwise avoid allocation. (This means that callers should not do their own buffering.)

All of the above can be configured using a WriterBuilder. However, a Writer has a couple of convenience constructors (from_path and from_writer) that use the default configuration.

Note that the default configuration of a Writer uses \n for record terminators instead of \r\n as specified by RFC 4180. Use the terminator method on WriterBuilder to set the terminator to \r\n if it's desired.

Methods

impl Writer<File>
[src]

Build a CSV writer with a default configuration that writes data to the given file path. The file is truncated if it already exists.

If there was a problem opening the file at the given path, then this returns the corresponding error.

Example

extern crate csv;

use std::error::Error;
use csv::Writer;

fn example() -> Result<(), Box<Error>> {
    let mut wtr = Writer::from_path("foo.csv")?;
    wtr.write_record(&["a", "b", "c"])?;
    wtr.write_record(&["x", "y", "z"])?;
    wtr.flush()?;
    Ok(())
}

impl<W: Write> Writer<W>
[src]

Build a CSV writer with a default configuration that writes data to wtr.

Note that the CSV writer is buffered automatically, so you should not wrap wtr in a buffered writer like io::BufWriter.

Example

extern crate csv;

use std::error::Error;
use csv::Writer;

fn example() -> Result<(), Box<Error>> {
    let mut wtr = Writer::from_writer(vec![]);
    wtr.write_record(&["a", "b", "c"])?;
    wtr.write_record(&["x", "y", "z"])?;

    let data = String::from_utf8(wtr.into_inner()?)?;
    assert_eq!(data, "a,b,c\nx,y,z\n");
    Ok(())
}

Serialize a single record using Serde.

# Example

This shows how to serialize normal Rust structs as CSV records. The fields of the struct are used to write a header row automatically. (Writing the header row automatically can be disabled by building the CSV writer with a WriterBuilder and calling the has_headers method.)

extern crate csv;
 #[macro_use]
 extern crate serde_derive;

 use std::error::Error;
 use csv::Writer;

 #[derive(Serialize)]
 struct Row<'a> {
     city: &'a str,
     country: &'a str,
     // Serde allows us to name our headers exactly,
     // even if they don't match our struct field names.
     #[serde(rename = "popcount")]
     population: u64,
 }

 fn example() -> Result<(), Box<Error>> {
     let mut wtr = Writer::from_writer(vec![]);
     wtr.serialize(Row {
         city: "Boston",
         country: "United States",
         population: 4628910,
     })?;
     wtr.serialize(Row {
         city: "Concord",
         country: "United States",
         population: 42695,
     })?;

     let data = String::from_utf8(wtr.into_inner()?)?;
     assert_eq!(data, "\
city,country,popcount
Boston,United States,4628910
Concord,United States,42695
");
     Ok(())
 }

# Rules

For the most part, any Rust type that maps straight-forwardly to a CSV record is supported. This includes structs, tuples and tuple structs. Other Rust types, such as Vecs, arrays, maps and enums have a more complicated story. In general, when working with CSV data, one should avoid nested sequences as much as possible.

Structs, tuples and tuple structs map to CSV records in a simple way. Tuples and tuple structs encode their fields in the order that they are defined. Structs will do the same only if has_headers has been disabled using WriterBuilder.

Nested sequences are supported in a limited capacity. Namely, they are flattened only when headers are not being written automatically. For example:

extern crate csv;
 #[macro_use]
 extern crate serde_derive;

 use std::error::Error;
 use csv::WriterBuilder;

 #[derive(Serialize)]
 struct Row {
     label: String,
     values: Vec<f64>,
 }

 fn example() -> Result<(), Box<Error>> {
     let mut wtr = WriterBuilder::new()
         .has_headers(false)
         .from_writer(vec![]);
     wtr.serialize(Row {
         label: "foo".to_string(),
         values: vec![1.1234, 2.5678, 3.14],
     })?;

     let data = String::from_utf8(wtr.into_inner()?)?;
     assert_eq!(data, "\
foo,1.1234,2.5678,3.14
");
     Ok(())
 }

If has_headers were enabled in the above example, then serialization would return an error. This applies to all forms of nested composite types because there's no obvious way to write headers that are in correspondence with the records.

Simple enums in Rust can be serialized. Namely, enums must either be variants with no arguments or variants with a single argument. For example, to serialize a field from either an integer or a float type, one can do this:

extern crate csv;
 #[macro_use]
 extern crate serde_derive;

 use std::error::Error;
 use csv::Writer;

 #[derive(Serialize)]
 struct Row {
     label: String,
     value: Value,
 }

 #[derive(Serialize)]
 enum Value {
     Integer(i64),
     Float(f64),
 }

 fn example() -> Result<(), Box<Error>> {
     let mut wtr = Writer::from_writer(vec![]);
     wtr.serialize(Row {
         label: "foo".to_string(),
         value: Value::Integer(3),
     })?;
     wtr.serialize(Row {
         label: "bar".to_string(),
         value: Value::Float(3.14),
     })?;

     let data = String::from_utf8(wtr.into_inner()?)?;
     assert_eq!(data, "\
label,value
foo,3
bar,3.14
");
     Ok(())
 }

Write a single record.

This method accepts something that can be turned into an iterator that yields elements that can be represented by a &[u8].

This may be called with an empty iterator, which will cause a record terminator to be written. If no fields had been written, then a single empty field is written before the terminator.

Example

extern crate csv;

use std::error::Error;
use csv::Writer;

fn example() -> Result<(), Box<Error>> {
    let mut wtr = Writer::from_writer(vec![]);
    wtr.write_record(&["a", "b", "c"])?;
    wtr.write_record(&["x", "y", "z"])?;

    let data = String::from_utf8(wtr.into_inner()?)?;
    assert_eq!(data, "a,b,c\nx,y,z\n");
    Ok(())
}

Write a single ByteRecord.

This method accepts a borrowed ByteRecord and writes its contents to the underlying writer.

This is similar to write_record except that it specifically requires a ByteRecord. This permits the writer to possibly write the record more quickly than the more generic write_record.

This may be called with an empty record, which will cause a record terminator to be written. If no fields had been written, then a single empty field is written before the terminator.

Example

extern crate csv;

use std::error::Error;
use csv::{ByteRecord, Writer};

fn example() -> Result<(), Box<Error>> {
    let mut wtr = Writer::from_writer(vec![]);
    wtr.write_byte_record(&ByteRecord::from(&["a", "b", "c"][..]))?;
    wtr.write_byte_record(&ByteRecord::from(&["x", "y", "z"][..]))?;

    let data = String::from_utf8(wtr.into_inner()?)?;
    assert_eq!(data, "a,b,c\nx,y,z\n");
    Ok(())
}

Write a single field.

One should prefer using write_record over this method. It is provided for cases where writing a field at a time is more convenient than writing a record at a time.

Note that if this API is used, write_record should be called with an empty iterator to write a record terminator.

Example

extern crate csv;

use std::error::Error;
use csv::Writer;

fn example() -> Result<(), Box<Error>> {
    let mut wtr = Writer::from_writer(vec![]);
    wtr.write_field("a")?;
    wtr.write_field("b")?;
    wtr.write_field("c")?;
    wtr.write_record(None::<&[u8]>)?;
    wtr.write_field("x")?;
    wtr.write_field("y")?;
    wtr.write_field("z")?;
    wtr.write_record(None::<&[u8]>)?;

    let data = String::from_utf8(wtr.into_inner()?)?;
    assert_eq!(data, "a,b,c\nx,y,z\n");
    Ok(())
}

Flush the contents of the internal buffer to the underlying writer.

If there was a problem writing to the underlying writer, then an error is returned.

Note that this also flushes the underlying writer.

Flush the contents of the internal buffer and return the underlying writer.

Trait Implementations

impl<W: Debug + Write> Debug for Writer<W>
[src]

Formats the value using the given formatter.

impl<W: Write> Drop for Writer<W>
[src]

A method called when the value goes out of scope. Read more