Rust Function: Read and Parse CSV with Error handling
Write a Rust function that reads a CSV file, parses it into structured data, and handles parsing errors.
Sample Solution:
Rust Code:
use std::fs; // Import the fs module for file handling
use std::error::Error; // Import the Error trait for error handling
use std::path::Path; // Import the Path struct for handling file paths
use csv::ReaderBuilder; // Import the ReaderBuilder struct from the csv crate for reading CSV files
// Define a struct to represent the data structure of each row in the CSV file
#[derive(Debug)]
struct Record {
name: String,
age: u32,
city: String,
}
// Function to read and parse the CSV file
fn read_csv(file_path: &str) -> Result<Vec<Record>, Box<dyn Error>> {
let file = fs::File::open(file_path)?; // Open the file
let mut reader = ReaderBuilder::new().has_headers(false).from_reader(file); // Create a CSV reader without assuming headers
let mut records = Vec::new(); // Initialize a vector to store parsed records
// Iterate over each record in the CSV file
for result in reader.records() {
let record = result?; // Unwrap the record or propagate any parsing errors
// Parse the fields of the record into the Record struct
let name = record.get(0).ok_or("Missing name field")?.to_string(); // Extract the name field
let age_str = record.get(1).ok_or("Missing age field")?; // Extract the age field as a string
let age: u32 = age_str.parse()?; // Parse the age string into a u32
let city = record.get(2).ok_or("Missing city field")?.to_string(); // Extract the city field
// Create a Record instance and push it to the records vector
records.push(Record { name, age, city });
}
Ok(records) // Return the parsed records vector
}
fn main() {
let file_path = "data.csv"; // Specify the path of the CSV file
let csv_data = "John,25,New York\nAlice,30,Los Angeles\nBob,35,Chicago"; // CSV data to write to the file
// Create the CSV file with the specified data
fs::write(file_path, csv_data).expect("Failed to create CSV file");
match read_csv(file_path) {
Ok(records) => {
println!("Parsed records:");
for record in records {
println!("{:?}", record);
}
}
Err(err) => eprintln!("Error reading CSV file: {}", err),
}
}
Output:
Parsed records: Record { name: "John", age: 25, city: "New York" } Record { name: "Alice", age: 30, city: "Los Angeles" } Record { name: "Bob", age: 35, city: "Chicago" }
Explanation:
Here's a brief explanation of the above Rust code:
- Imports: The code imports the necessary modules and structs from the standard library (std::fs, std::error::Error, std::path::Path) and from the "csv" crate (csv::ReaderBuilder).
- Record Struct: It defines a struct "Record" with fields 'name', 'age', and 'city' to represent the structure of each row in the CSV file. The #[derive(Debug)] attribute is used to automatically derive the "Debug" trait for pretty printing.
- read_csv Function: This function takes a file path as input and returns a "Result" containing a vector of "Record" instances or an error. It opens the file, creates a CSV reader without assuming headers, and iterates over each record in the file. For each record, it parses the fields into a "Record" struct and adds it to a vector. If any parsing error occurs, it returns the error.
- main Function: In the "main()" function, it specifies the file path for the CSV file and creates sample CSV data. It then creates the CSV file with the sample data using fs::write. Next, it calls the "read_csv()" function to parse the CSV file. If parsing is successful, it prints the parsed records. If an error occurs, it prints an error message.
Rust Code Editor:
Previous: Rust Function: Read file with Error handling.
Next: Rust Program: Count Lines in File with Error Handling.
What is the difficulty level of this exercise?
Test your Programming skills with w3resource's quiz.
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics