由于上篇写的序列化给大家造成一些困惑或者是词不达意,亦或是给大家理解序列化造成了一定的误解,我深感抱歉,序列化我将重新构思来写,然后把底层的核心原理以及设计思想都会讲清楚,还请大家耐心等待,今天给大家带来使用rust读取csv文件的知识,我们知道csv可以直接导入到数据库,使用逗号分隔开,还能和excel兼容,因此在一些数据处理上常会用到它,我们有必要一探究竟。
将记录序列化为 CSV
我们通过一个例子来展示如何序列化 Rust 元组。csv::writer 支持从 Rust 类型到 CSV 记录的自动序列化。write_record 只写入包含字符串数据的简单记录。具有更复杂值(如数字、浮点和选项)的数据使用 serialize 进行序列化。因为 csv::writer 使用内部缓冲区,所以在完成时总是显式刷新 flush。
use error_chain::error_chain;
use std::io;
error_chain! {
foreign_links {
CSVError(csv::Error);
IOError(std::io::Error);
}
}
fn main() -> Result<()> {
let mut wtr = csv::Writer::from_writer(io::stdout());
wtr.write_record(&["Name", "Place", "ID"])?;
wtr.serialize(("Mark", "Sydney", 87))?;
wtr.serialize(("Ashley", "Dublin", 32))?;
wtr.serialize(("Akshat", "Delhi", 11))?;
wtr.flush()?;
Ok(())
}
用 Serde 将记录序列化为 CSV
serde和csv结合会擦出什么火花了?下面的实例展示如何使用 serde crate 将自定义结构体序列化为 CSV 记录。
use error_chain::error_chain;
use serde::Serialize;
use std::io;
error_chain! {
foreign_links {
IOError(std::io::Error);
CSVError(csv::Error);
}
}
#[derive(Serialize)]
struct Record<'a> {
name: &'a str,
place: &'a str,
id: u64,
}
fn main() -> Result<()> {
let mut wtr = csv::Writer::from_writer(io::stdout());
let rec1 = Record { name: "Mark", place: "Melbourne", id: 56};
let rec2 = Record { name: "Ashley", place: "Sydney", id: 64};
let rec3 = Record { name: "Akshat", place: "Delhi", id: 98};
wtr.serialize(rec1)?;
wtr.serialize(rec2)?;
wtr.serialize(rec3)?;
wtr.flush()?;
Ok(())
}
转换CSV文件的列
包含颜色名称和十六进制颜色值的 CSV 文件转换为具有颜色名称和 rgb 颜色值的 CSV 文件。使用 csv crate 读写 csv 文件,使用 serde crate 对行输入字节进行反序列化,对行输出字节进行序列化。
详细请参阅 csv::Reader::deserialize、serde::Deserialize,以及 std::str::FromStr。
use error_chain::error_chain;
use csv::{Reader, Writer};
use serde::{de, Deserialize, Deserializer};
use std::str::FromStr;
error_chain! {
foreign_links {
CsvError(csv::Error);
ParseInt(std::num::ParseIntError);
CsvInnerError(csv::IntoInnerError<Writer<Vec<u8>>>);
IO(std::fmt::Error);
UTF8(std::string::FromUtf8Error);
}
}
#[derive(Debug)]
struct HexColor {
red: u8,
green: u8,
blue: u8,
}
#[derive(Debug, Deserialize)]
struct Row {
color_name: String,
color: HexColor,
}
impl FromStr for HexColor {
type Err = Error;
fn from_str(hex_color: &str) -> std::result::Result<Self, Self::Err> {
let trimmed = hex_color.trim_matches('#');
if trimmed.len() != 6 {
Err("Invalid length of hex string".into())
} else {
Ok(HexColor {
red: u8::from_str_radix(&trimmed[..2], 16)?,
green: u8::from_str_radix(&trimmed[2..4], 16)?,
blue: u8::from_str_radix(&trimmed[4..6], 16)?,
})
}
}
}
impl<'de> Deserialize<'de> for HexColor {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
FromStr::from_str(&s).map_err(de::Error::custom)
}
}
fn main() -> Result<()> {
let data = "color_name,color
red,#ff0000
green,#00ff00
blue,#0000FF
periwinkle,#ccccff
magenta,#ff00ff"
.to_owned();
let mut out = Writer::from_writer(vec![]);
let mut reader = Reader::from_reader(data.as_bytes());
for result in reader.deserialize::<Row>() {
let res = result?;
out.serialize((
res.color_name,
res.color.red,
res.color.green,
res.color.blue,
))?;
}
let written = String::from_utf8(out.into_inner()?)?;
assert_eq!(Some("magenta,255,0,255"), written.lines().last());
println!("{}", written);
Ok(())
}
最后希望大家能关注我的公众号:花说编程