【Rust每周一庫】csv – 文件讀寫庫

  • 2020 年 2 月 20 日
  • 筆記

這次搬運的庫是很多數據分析師、數據科學家、以及金融分析師常用的csv文件庫。

csv

用Rust實現的一個高性能、靈活的CSV讀寫器,支援Serde.

官方文檔:

https://docs.rs/csv

使用方法:

將以下配置加進你的 Cargo.toml:

[dependencies]  csv = "1.1"  

例子:

簡單示範如何從stdin讀取CSV數據並通過stdout將每一條記錄列印出來。

use std::error::Error;  use std::io;  use std::process;    fn example() -> Result<(), Box<dyn Error>> {      // 建立 CSV 讀取器並且遍歷每一條記錄。      let mut rdr = csv::Reader::from_reader(io::stdin());      for result in rdr.records() {          // 遍歷器會返回Result<StringRecord, Error>,所以我們在這裡檢查是否有錯誤。          let record = result?;          println!("{:?}", record);      }      Ok(())  }    fn main() {      if let Err(err) = example() {          println!("error running example: {}", err);          process::exit(1);      }  }  

以上的例子可以用以下命令運行:

$ git clone git://github.com/BurntSushi/rust-csv  $ cd rust-csv  $ cargo run --example cookbook-read-basic < examples/data/smallpop.csv  

與 Serde一起使用時:

示範如何從stdin讀取CSV數據並且將數據映射到訂製結構體。結構體中的成員名稱會默認與CSV數據中的表頭相對應。

use std::error::Error;  use std::io;  use std::process;    use serde::Deserialize;    #[derive(Debug, Deserialize)]  struct Record {      city: String,      region: String,      country: String,      population: Option<u64>,  }    fn example() -> Result<(), Box<dyn Error>> {      let mut rdr = csv::Reader::from_reader(io::stdin());      for result in rdr.deserialize() {          // 這裡需要注意,我們需要為自動反序列化提供一個類型提示          let record: Record = result?;          println!("{:?}", record);      }      Ok(())  }    fn main() {      if let Err(err) = example() {          println!("error running example: {}", err);          process::exit(1);      }  }  

以上的例子可以用以下命令運行:

$ git clone git://github.com/BurntSushi/rust-csv  $ cd rust-csv  $ cargo run --example cookbook-read-serde < examples/data/smallpop.csv  

下面的例子演示了如何將數據以CSV數據形式寫入stdout:

extern crate csv;    use std::error::Error;  use std::io;  use std::process;    fn example() -> Result<(), Box<Error>> {      let mut wtr = csv::Writer::from_writer(io::stdout());        // 當不與Serde共同使用時,表頭可以按照與其他記錄同樣的方式寫入      wtr.write_record(&["city", "region", "country", "population"])?;      wtr.write_record(&["Southborough", "MA", "United States", "9686"])?;      wtr.write_record(&["Northbridge", "MA", "United States", "14061"])?;      wtr.flush()?;      Ok(())  }    fn main() {      if let Err(err) = example() {          println!("error running example: {}", err);          process::exit(1);      }  }  

以上的例子可以用以下命令運行:

$ git clone git://github.com/BurntSushi/rust-csv  $ cd rust-csv  $ cargo run --example cookbook-write-basic > /tmp/simplepop.csv  

與Serde一起使用時:

extern crate csv;  #[macro_use]  extern crate serde_derive;    use std::error::Error;  use std::io;  use std::process;    #[derive(Debug, Serialize)]  struct Record {      city: String,      region: String,      country: String,      population: Option<u64>,  }    fn example() -> Result<(), Box<Error>> {      let mut wtr = csv::Writer::from_writer(io::stdout());        // 當用結構體通過Serde寫入記錄時,表頭會被自動寫入      wtr.serialize(Record {          city: "Southborough".to_string(),          region: "MA".to_string(),          country: "United States".to_string(),          population: Some(9686),      })?;      wtr.serialize(Record {          city: "Northbridge".to_string(),          region: "MA".to_string(),          country: "United States".to_string(),          population: Some(14061),      })?;      wtr.flush()?;      Ok(())  }    fn main() {      if let Err(err) = example() {          println!("error running example: {}", err);          process::exit(1);      }  }  

以上的例子可以用以下命令運行:

$ git clone git://github.com/BurntSushi/rust-csv  $ cd rust-csv  $ cargo run --example cookbook-write-serde > /tmp/simplepop.csv  

例子:用過濾器搜索

extern crate csv;    use std::env;  use std::error::Error;  use std::io;  use std::process;    fn run() -> Result<(), Box<Error>> {      // 通過位置參數拿到查詢語句      let query = match env::args().nth(1) {          None => return Err(From::from("expected 1 argument, but got none")),          Some(query) => query,      };        // 通過stdin建立CSV讀取器      // 通過stdout建立CSV寫入器      let mut rdr = csv::Reader::from_reader(io::stdin());      let mut wtr = csv::Writer::from_writer(io::stdout());        // 在讀取數據記錄之前,先寫入表頭記錄      wtr.write_record(rdr.headers()?)?;        // 通過rdr遍歷所有記錄,然後通過wre寫入只含有「query」的記錄      for result in rdr.records() {          let record = result?;          if record.iter().any(|field| field == &query) {              wtr.write_record(&record)?;          }      }        // CSV寫入器使用內部緩衝器,要記得完成後刷新清空。      wtr.flush()?;      Ok(())  }    fn main() {      if let Err(err) = run() {          println!("{}", err);          process::exit(1);      }  }  

在編譯之後,運行這段程式碼時加入 MA 作為查詢語句,可以看到結果中只有一條記錄複合查詢條件:

$ cargo build  $ ./csvtutor MA < uspop.csv  City,State,Population,Latitude,Longitude  Reading,MA,23441,42.5255556,-71.0958333  

本文來源於 cookbook.