< 返回版块

0x5F3759DF 发表于 2020-01-17 01:40

Tags:parser,csv,解析器

这次搬运的库是很多数据分析师、数据科学家、以及金融分析师常用的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.


Ext Link: https://docs.rs/csv/1.0.0/csv/

评论区

写评论

还没有评论

1 共 0 条评论, 1 页