CSV spreadsheet files are suitable for storing tabular data in a relatively portable way.

The CSV format is flexible but somewhat ill-defined.

For present purposes, authors may assume that the data fields contain no commas, backslashes, or quotation marks.



Task

Read a CSV file, change some values and save the changes back to a file.

For this task we will use the following CSV file:

C1,C2,C3,C4,C5
1,5,9,13,17
2,6,10,14,18
3,7,11,15,19
4,8,12,16,20

Suggestions


 Show how to add a column, headed 'SUM', of the sums of the rows.
 If possible, illustrate the use of built-in or standard functions, methods, or libraries, that handle generic CSV files.



use std::error::Error;
use std::num::ParseIntError;
use csv::{Reader, Writer};
 
fn main() -> Result<(), Box<dyn Error>> {
    let mut reader = Reader::from_path("data.csv")?;
    let mut writer = Writer::from_path("output.csv")?;
 
    // headers() returns an immutable reference, so clone() before appending
    let mut headers = reader.headers()?.clone();
    headers.push_field("SUM");
    writer.write_record(headers.iter())?;
 
    for row in reader.records() {
        let mut row = row?;
 
        // `sum` needs the type annotation so that `parse::<i64>` knows what error type to return
        let sum: Result<_, ParseIntError> = row.iter().try_fold(0, |accum, s| {
            Ok(accum + s.parse::<i64>()?)
        });
 
        row.push_field(&sum?.to_string());
        writer.write_record(row.iter())?;
    }
 
    writer.flush()?;
    Ok(())
}