use std::fs::File;
use serde::de::DeserializeOwned;
use crate::IResult;
pub fn save<T: serde::Serialize>(arr: Vec<T>, path: &str) -> Result<(), Box<dyn std::error::Error>> {
let mut wtr = csv::Writer::from_path(path)?;
for item in arr {
wtr.serialize(item)?;
}
wtr.flush()?;
Ok(())
}
pub struct CsvHander {
file: csv::Writer<File>,
}
impl CsvHander {
pub fn new(path: &str) -> IResult<Self> {
debug!("csv_util::CsvHander::new: {}", path);
let file = std::fs::File::options().create_new(true).append(true).open(path)?;
let wtr: csv::Writer<File> = csv::WriterBuilder::new().has_headers(true).from_writer(file);
let r = Self { file: wtr };
Ok(r)
}
pub fn save_append<T: serde::Serialize>(&mut self, arr: Vec<T>) -> IResult<()> {
for item in arr {
self.file.serialize(item)?;
}
self.file.flush()?;
Ok(())
}
}
pub fn read<R: DeserializeOwned>(path: &str) -> Result<Vec<R>, Box<dyn std::error::Error>> {
let mut rdr = csv::Reader::from_path(path)?;
let mut data = vec![];
let iter: csv::DeserializeRecordsIter<'_, std::fs::File, R> = rdr.deserialize();
for (i, row) in iter.into_iter().enumerate() {
let row = match row {
Ok(row) => row,
Err(e) => {
let i = i + 1;
error!("read csv {path}:{i} error: {}", e);
continue;
}
};
data.push(row);
}
Ok(data)
}
#[test]
fn test_csv() {
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Test {
name: String,
age: i32,
}
let data = vec![
Test { name: "张三".to_string(), age: 18 },
Test { name: "李四".to_string(), age: 20 },
Test { name: "3".to_string(), age: 35 },
];
let path = "test2.csv";
save(data, path).unwrap();
let data: Vec<Test> = read(path).unwrap();
println!("read: {:?}", data);
assert_eq!(data[0].name, "张三");
assert_eq!(data[1].name, "李四");
}
#[test]
fn test_csv_hander() {
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Test {
name: String,
age: i32,
}
let path = "test2.csv";
let mut handler = CsvHander::new(path).unwrap();
let data = vec![
Test { name: "张三".to_string(), age: 18 },
];
handler.save_append(data).unwrap();
handler.save_append(vec![
Test { name: "李四".to_string(), age: 20 },
Test { name: "3".to_string(), age: 35 },
]).unwrap();
assert_eq!(read::<Test>(path).unwrap()[0].name, "张三");
assert_eq!(read::<Test>(path).unwrap()[1].name, "李四");
}