0

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.

Anonymous Person
  • 1,437
  • 8
  • 26
  • 47
  • My apologies. I will change it now. It was just the outputs and not the code itself that I pasted the images of. – Anonymous Person Jan 10 '23 at 06:52
  • Anything that can read CSV knows what to do with the quotes. It's a bit like complaining that an HTML writer outputs `"` somewhere instead of `"`. They have exactly the same semantic meaning. It's likely escaping anything except alphanumeric characters with quotes as this can make the file less likely to confuse other parsers that may try to e.g. infer the separator character. – cdhowie Jan 10 '23 at 06:56
  • 1
    Are you sure you're using `clap` I've never seen anyone use it to parse csv, also you never define `column_names` anywhere in your snippets. – cafce25 Jan 10 '23 at 06:57
  • OK @cafce25 - I've removed the images. I hope now it's easier to read. – Anonymous Person Jan 10 '23 at 06:59
  • @cafce25 - Yes I am using clap. FYI, it prints to rows and everything just fine, so the arguments are being passed around just fine, so yes, I am pretty sure Clap is what I am using. And I've added `column_names` now. Sorry about that. – Anonymous Person Jan 10 '23 at 07:03
  • None of the code shown uses clap, clap is not a csv parsing library, I say your using clap is unrelated. – cafce25 Jan 10 '23 at 07:08
  • @cdhowie - So are you saying that it's expected behaviour, that when you print `StringRecord`, which `column_names` is, somehow, the first element is not quoted and the other elements are? – Anonymous Person Jan 10 '23 at 07:09
  • @AnonymousPerson The first element does not contain any non-alphanumeric characters. Try throwing a `(` in it like the other two have, I bet it'll become quoted. – cdhowie Jan 10 '23 at 07:11
  • @cafce25 - OK, yes that's unrelated, which is why I also did not tag my question with it. I thought I should have pointed it out though. – Anonymous Person Jan 10 '23 at 07:11
  • @cdhowie - I have not tried _that_, but I have tried removing the braces, and that hadn't changed anything. Let me try what you suggested real quick. – Anonymous Person Jan 10 '23 at 07:13
  • @cdhowie - that didn't work unfortunately, meaning, only the first element was without quotes - Just as before. I'll paste the output in a bit, not at a computer right now. – Anonymous Person Jan 10 '23 at 09:07

1 Answers1

1

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

cafce25
  • 15,907
  • 4
  • 25
  • 31