How do I update a field in a csv::ByteRecord?

2019-02-21 03:18发布

问题:

I am trying to parse a CSV file and if a certain field matches, update a certain field with a different value, but I'm not sure on how to do this.

My code:

extern crate csv;

use std::error::Error;

fn run(file: &str, output: &str) -> Result<(), Box<Error>> {
    let mut rdr = csv::Reader::from_path(file)?;
    let mut wtr = csv::Writer::from_path(output)?;

    wtr.write_record(rdr.byte_headers()?);
    for result in rdr.byte_records() {
        let mut record = result?;
        if &record[0] == "05V".as_bytes() && &record[4] == "4".as_bytes() {
            // let record[4] = "2"; -> Not sure how to update the field
        }
        wtr.write_byte_record(&record);
    }
    Ok(())
}

How can I update the field if the record matches the conditions?

回答1:

You don't. A ByteRecord (and a StringRecord by extension) store all of the field's data in a single tightly-packed Vec<u8>. You cannot easily access this Vec to modify it and the currently exposed mutation methods are too coarse to be useful in this case. You could remove fields from the end of the record or clear the entire thing, but not replace one field.

Instead, you can create a brand new ByteRecord when needed and output that:

for result in rdr.byte_records() {
    let input_record = result?;

    let output_record = if &input_record[0] == b"05V" && &input_record[4] == b"4" {
        input_record
            .into_iter()
            .enumerate()
            .map(|(i, v)| if i == 4 { b"2" } else { v })
            .collect()
    } else {
        input_record
    };
    wtr.write_byte_record(&output_record);
}


标签: csv rust