Rustの勉強がてら、以前、bashで実装した下記記事のRust版を実装した。
(CANログから特定フレームだけを取り出す)
Rustのビルド環境が必要だが、約20万行のログファイルに対して、bash版の3分の1の時間で処理可能。
使用方法
下記コードをビルドしてできたexeファイルを、.ascファイルがあるディレトリに置き、実行するだけ。
実装
- Rust初コーディングだったので、おかしな点があれば指摘お願いします。
- Qiita投稿用にコードをアレンジしたので、もしかしたらおかしな点があるかもしれません。(cargo runは確認済み)
extern crate regex;
use std::fs;
use std::io::{BufRead, Write, BufReader, BufWriter};
use regex::Regex;
// 必要に応じて適切な条件を設定する
const CANID: &str = "XXX"; // CANID
fn main()
{
// カレントディレクトリから.ascファイルを検索
SeachAscFile();
}
// カレントディレクトリから.ascファイルを検索
fn SeachAscFile()
{
let files = fs::read_dir("./").unwrap();
for f in files
{
let filename = f.unwrap().path().display().to_string();
if filename.find(".asc") != None
{
// .ascファイル読み込み
ReadAscFile(&filename);
}
}
}
// .ascファイル読み込み
fn ReadAscFile(ascfilename: &String)
{
// 出力ファイル名設定(拡張子置換で対応)
let outfilename = ascfilename.to_string().replace(".asc", "_out.txt");
// ログデータ格納変数
let mut logdatabuffer = "".to_string();
// ファイル出力用バッファ
let mut writebuf = BufWriter::new(fs::File::create(outfilename).unwrap());
// 1行ずつ読み込み
let file = fs::File::open(ascfilename).unwrap(); // Ignore errors.
for line in BufReader::new(file).lines()
{
let content: String = line.unwrap().to_string(); // 行データを文字列型に変換
// 指定CANIDのログを抽出
logdatabuffer = ExtractSpecificFrame(&content);
// logdatabufferのサイズが0でなければ対象CANIDのデータが抽出されたことを意味する
if logdatabuffer.len() != 0
{
writebuf.write_all(logdatabuffer.as_bytes()); // 出力データをバッファリング
writebuf.write_all("\n".as_bytes()); // 改行コードを追加
}
}
// ファイル出力
writebuf.flush();
}
// 指定CANIDのログを抽出
fn ExtractSpecificFrame(content: &String) -> String
{
let mut ret_str: String = "".to_string();
let repattern = format!("{}", CANID); // 正規表現のパターンを文字列リテラルの結合で設定
let re = Regex::new(&repattern).unwrap(); // 正規表現パターン設定
if re.is_match(&content) == true
{
ret_str = content.to_string();
}
return ret_str;
}