用Rust读CSV、excel文件时,往往会碰到中文字符,用标准库的方法是有问题的。那如何办?
一、外部库 encoding
在cargo.toml文件[dependencies]下加入:
encoding = "0.2"
csv = "1.3.0"
二、有中文字符下CSV文件的读和写
use encoding::{self,DecoderTrap, EncoderTrap, Encoding,all::GB18030};
use std::io::{self,Read};
use std::fs::{self,File};
use std::{error::Error, process};
use csv;
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt};
fn example(content:&str) -> Result<(), Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(content.as_bytes());
for result in rdr.records() {
let record = result?;
println!("序号 {:?} 产品名称{:?} 成立日期{:?}", &record[0],&record[1],&record[2]); // 可以正常读出每一个单元的数据了
}
Ok(())
}
fn main() {
// 只有注册 subscriber 后, 才能在控制台上看到日志输出
tracing_subscriber::registry()
.with(fmt::layer())
.init();
let content = file_read(r"C:\Users\Desktop\test.csv").unwrap();
//println!("{}",input);
//tracing::info!(content, "csv from tracing");
if let Err(err) = example(&content) {
println!("error running example: {}", err);
process::exit(1);
}
//fs::write(".\\output.txt",input).unwrap();
}
// read GB18030
fn file_read(path: &str) -> io::Result<String> {
let mut f = File::open(path)?;
let mut reader: Vec<u8> = Vec::new();
f.read_to_end(&mut reader).ok().expect("can not read file");
let content: String = GB18030.decode(&reader, DecoderTrap::Replace).unwrap();
Ok(content)
}
// write
// fn file_write(text: io::Result<Vec<String>>, _path: &str) -> io::Result<()> {
// let text = text.unwrap();
// let mut buffer = File::create(_path)?;
// for tx in text {
// //let tx_u8: Vec<u8> = tx.chars().map(|x| x as u8).collect(); 为什么这样写不行?
// let tx_u8: Vec<u8> = GB18030.encode(&tx, EncoderTrap::Strict).unwrap();
// buffer.write_all(&tx_u8)?;
// }
// Ok(())
// }
输出:
3、其它
我碰到过同样的含有中文的表格内容,在.xlsx文件中就是无法读出,报"invalid sequence"等错误,但同样的,copy到.csv文件中,却是正常可以打开的。