csvrustcsv-header

Issue printing header using Rust's CSV crate


Here is my setup:

  1. I am reading a csv file, the path to which is passed into the built exe as an argument, and I am using the crate Clap for it.
  2. It all reads the file with no problem, but I am having trouble printing the headers.
  3. I'd like to be able to print the headers without the quotes, but when I print it, only the first header/column gets printed without them, and the remaining ones do not.
  4. Here's what I mean:

This is the part of the code that prints the header:

let mut rdr = csv::Reader::from_path(file)?;

let column_names = rdr.headers();

println!("{}", match column_names {
        Ok(v) => v.as_slice(),
        Err(_) => "Error!"
});

With this, this is what the output is:

warning: `csv_reader` (bin "csv_reader") generated 2 warnings
    Finished release [optimized] target(s) in 0.13s
     Running `target\release\csv_reader.exe -f C:\nkhl\Projects\dataset\hw_25000.csv`
Index "Height(Inches)" "Weight(Pounds)"
()

As you can see, Index does not get printed with the quotes, which is how I'd like the others to be printed. Printing with Debug marker enabled, I get this:

let mut rdr = csv::Reader::from_path(file)?;

let column_names = rdr.headers();

println!("{:?}", match column_names {
        Ok(v) => v.as_slice(),
        Err(_) => "Error!"
});
warning: `csv_reader` (bin "csv_reader") generated 2 warnings
    Finished release [optimized] target(s) in 1.92s
     Running `target\release\csv_reader.exe -f C:\nkhl\Projects\dataset\hw_25000.csv`
"Index \"Height(Inches)\" \"Weight(Pounds)\""
()

The CSV can be found here: https://people.sc.fsu.edu/~jburkardt/data/csv/hw_25000.csv

This is how it looks:

"Index", "Height(Inches)", "Weight(Pounds)"
1, 65.78331, 112.9925
2, 71.51521, 136.4873
3, 69.39874, 153.0269

I hope I am doing something utterly silly, but for the life of me, I am unable to figure it out.


Solution

  • Your csv data contains extraneous spaces after the commas, because of that Rusts csv thinks that the quotes around Height(Inches) are part of the header, not meant to escape them. Unfortunately the lack of standardization around csv makes both interpretations valid.

    You can use trim to get rid of the extra spaces:

    let data: &[u8] = include_bytes!("file.csv");
    let mut rdr = csv::ReaderBuilder::new().trim(csv::Trim::All).from_reader(data);
    

    But csv does the unquoting before it applies the trim so this does still leave you with the same problem. You can additionaly disable quoting to at least get the same behaviour on all columns:

    let mut rdr = csv::ReaderBuilder::new().quoting(false).trim(csv::Trim::All).from_reader(data);
    

    If you somehow can remove the spaces from your csv file it works just fine:

    fn main() {
        let data: &[u8] = br#""Index","Height(Inches)","Weight(Pounds)"
    1,65.78331,112.9925
    2,71.51521,136.4873
    3,69.39874,153.0269"#;
        let mut rdr = csv::Reader::from_reader(data);
        let hd = rdr.headers().unwrap();
        println!("{}", hd.as_slice());
        // prints `IndexHeight(Inches)Weight(Pounds)` without any `"`
    }
    

    Playground