🦀
C++erのRust入門4:CSV
Rust で CSV を読む方法について。
CSV クレートの追加
Rust で CSV を読む場合は、 csv クレート を使うのが一般的らしい。
cargo add csv
CSV をとりあえず読み込む
手っ取り早く取りあえず CSV ファイルを読むだけなら、以下が一番手っ取り早いみたい。
サンプルデータは私がこの1年ほど体重をCSVで記録してるので、それを適当に4行ほど切り出したもの。
-
year
: 整数 年 -
month
: 整数 月 -
day
: 整数 日付 -
hour
: 整数 時 -
minute
: 整数 分 -
weight
: 浮動小数点数 デブ加減[kg] -
fat
: 浮動小数点数 デブ度[%]- 最初は記録してなかったので ?? というデータあり
実行結果はこんな感じになった。
StringRecord(["2022", "3", "20", "5", "58", "92.9", "??"])
StringRecord(["2022", "7", "30", "10", "29", "84.7", "??"])
StringRecord(["2022", "7", "31", "6", "41", "85.5", "25.0"])
StringRecord(["2023", "5", "1", "13", "45", "75.8", "20.8"])
型に変換する
StringRecord
だとインデックスでアクセスする。
それよりは専用の型に変換した方が何かと扱いやすいよね。
#[derive(Debug, Copy, Clone)]
struct Entry {
year: u16,
month: u8,
day: u8,
hour: u8,
minute: u8,
weight: f32,
fat: Option<f32>
}
手動で変換してもいいけど、csv クレート は Serde クレート という型を Serialize/Deserialize するためのクレートに対応しているらしく、これを使うのが簡単みたい。
Serde クレートの追加
以下のコマンドで Serde クレート をプロジェクトに追加する。
-F derive
をつけないと #[derive]
が使えない。
cargo add serde -F derive
Serialize, Deserializeの実装
単純なものは #[derive(Serialize, Deserialize)]
とするだけで実装できてしまう。
ただ、今回の体脂肪率 fat
は Option
で、このままではエラーが発生する。
なので、独自にシリアライズとデシリアライズの関数をfat_format
モジュールに実装する。
- Serialize:
pub fn serialize<S>(value: &型, s: S) -> Result<S::Ok, S::Error> where S: Serializer
- Deserialize:
pub fn deserialize<'d, D>(d: D) -> Result<型, D::Error> where D: Deserializer<'d>
なお、どちらも pub
が必須で、型は今回は Option<f32>
である。
CSV からデシリアライズする
reader.records()
を reader.deserialize()
にして、 let data: Entry
で Entry
を指定する。
結果は以下のようになった。
Entry { year: 2022, month: 3, day: 20, hour: 5, minute: 58, weight: 92.9, fat: None }
Entry { year: 2022, month: 7, day: 30, hour: 10, minute: 29, weight: 84.7, fat: None }
Entry { year: 2022, month: 7, day: 31, hour: 6, minute: 41, weight: 85.5, fat: Some(25.0) }
Entry { year: 2023, month: 5, day: 1, hour: 13, minute: 45, weight: 75.8, fat: Some(20.8) }
シリアライズする
read_csv_sample2
で読み出した結果をそのまま標準出力に出してみる。
結果は以下。OKOK.
year,month,day,hour,minute,weight,fat
2022,3,20,5,58,92.9,??
2022,7,30,10,29,84.7,??
2022,7,31,6,41,85.5,25.0
2023,5,1,13,45,75.8,20.8
Discussion