📖
rust-csvのつかいかた
はじめに
Rustにはかなり古くから整備されてきた超有能CSVパースライブラリが存在します.
こちらがcrates.ioのページです.
公式のドキュメントはこちらです.
この記事の作成にあたっては、これらのドキュメントに加え、
以下のサイトを参考にさせていただきました.
依存関係のインストール
cargo add csv
で依存関係に追加しましょう.
次のように追加されるはずです.
Cargo.toml
[dependencies]
csv = "1.1.6"
シンプルな使用方法
CSVをパースして表示するだけのごくシンプルなプログラムを考えます.
コマンドライン引数からファイルパスを読み取り、C言語でいうところのfopenを作成しファイルインスタンスを作成、CSVパーサーに渡しています.
main.rs
extern crate csv;
use std::env;
use std::error::Error;
use std::ffi::OsString;
use std::fs::File;
use std::process;
fn get_first_arg() -> Result<OsString, Box<dyn Error>> {
match env::args_os().nth(1) {
None => Err(From::from("expected 1 argument, but got none")),
Some(file_path) => Ok(file_path),
}
}
fn fopen(path: &OsString) -> Result<File, Box<dyn Error>> {
let file = File::open(path)?;
Ok(file)
}
fn csv_parse(file: File) -> Result<(), Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(file);
for result in rdr.records() {
let record = result?;
println!("{:?}", record);
}
Ok(())
}
fn main() {
let file_path = match get_first_arg() {
Ok(file_path) => file_path,
Err(err) => {
eprintln!("Error: {}", err);
process::exit(1);
}
};
match csv_parse(fopen(&file_path).unwrap()) {
Ok(_) => println!("Successfully parsed CSV"),
Err(err) => {
eprintln!("Error: {}", err);
process::exit(1);
}
}
}
このとき、返されているrecord
の型はcsv::StringRecord
構造体です.
1行目読み取られない問題
このCSVパーサー、1行目はタイトル行としてデフォルトで読み飛ばす設定になっているらしいです.
ReaderBuilder::has_headers
の設定を書き換えると1行目も読み込めます
fn csv_parse(file: File) -> Result<(), Box<dyn Error>> {
let mut rdr = csv::ReaderBuilder::new()
.has_headers(false)
.from_reader(file);
for result in rdr.records() {
let record = result?;
println!("{:?}", record);
}
Ok(())
}
1行1列目だけ読み込む
fn csv_parse(file: File) -> Result<String, Box<dyn Error>> {
let mut rdr = csv::ReaderBuilder::new()
.has_headers(false)
.from_reader(file);
let first_line = rdr.records().next();
match first_line {
Some(Ok(record)) => Ok(record[0].to_owned()),
Some(Err(err)) => Err(From::from(err)),
None => Err(From::from("No data found in CSV file")),
}
}
Discussion