実現したいこと
ここに実現したいことを箇条書きで書いてください。
前提
勉強を兼ねてRustでCLIツールを作っているのでRustで作りたいです。
表示に関してindicatifクレートを使う予定です
フォルダ内のファイル捜査に関してはread_dirを使っています。
発生している問題・エラーメッセージ
rust
1error[E0382]: use of moved value: `files` 2 --> src\main.rs:35:17
ファイル数を把握する時点で所有権が移ってしまっています。
所有権を移さずに個数を把握することはできないのでしょうか?
該当のソースコード
rust
1fn main() -> Result<(), Box<dyn Error>> {2 println!("ファイルをまとめます");3 // エクセルファイルが格納されているフォルダのパス4 let folder_path = r"\example";5 let files = read_dir(folder_path)?;6 7 // 出力先のパス8 let output_path = r"\example.csv";9 // csv::WriterBuilderに渡す前にBOMを書き込んでおく。10 11 println!("保存フォルダ:{}",folder_path);12 println!("ファイル作成中...:{}",output_path);13 14 let output = File::create(output_path)?;15 let mut wtr = BufWriter::new(output);16 wtr.write_all(BOM)?;17 18 let mut wtr = WriterBuilder::new()19 .terminator(Terminator::CRLF)20 .from_writer(wtr);21 22 let max_count = files.cloned();23 24 let mut is_head_writed = false;25 // フォルダ内の各Excelファイルに対して処理を実行26 for file in files {27 let file_path = file?.path();28 if let Some(extension) = file_path.extension() {29 // 拡張子がxlsxのファイルのみ処理する30 if extension == "xlsx" {31 // エクセルファイルを開く32 let mut workbook: Xlsx<_> = open_workbook(&file_path)?;33 workbook 34 .load_tables()35 .unwrap_or_else(|err| eprintln!("IO Error -> {}",err));36 37 if let Some(Ok(table)) = workbook.table_by_name("exampleTable"){38 if false == is_head_writed {39 wtr 40 .write_record(table.columns())41 .unwrap_or_else(|err| eprintln!("IO Error -> {}",err));42 is_head_writed = true;43 }44 for row in table.data().rows(){45 if "" != row[1].to_string() {46 wtr 47 .write_record(row.iter().map(|f|f.to_string()).collect::<Vec<_>>())48 .unwrap_or_else(|err| eprintln!("IO Error -> {}",err));49 }else {50 // データが空なのでskip51 }52 }53 }54 }55 }56 }57 wtr.flush()?;58 println!("作成完了!");59 Ok(())60}
試したこと
以下のようにしたら実現するのですが、
カウント時とファイル処理時の2回、フォルダ捜査と絞り込みを行っているのが気に食わないです。
rust
1fn main() -> Result<(), Box<dyn Error>> {2 println!("ファイルをまとめます");3 // エクセルファイルが格納されているフォルダのパス4 let folder_path = r"\example";5 6 // 出力先のパス7 let output_path = r"\example.csv";8 // csv::WriterBuilderに渡す前にBOMを書き込んでおく。9 10 println!("保存フォルダ:{}",folder_path);11 println!("ファイル作成中...:{}",output_path);12 13 let output = File::create(output_path)?;14 let mut wtr = BufWriter::new(output);15 wtr.write_all(BOM)?;16 17 let mut wtr = WriterBuilder::new()18 .terminator(Terminator::CRLF)19 .from_writer(wtr);20 21 let file_count: u64 = read_dir(folder_path)?22 .filter_map(|entry| {23 let path = entry.ok()?.path();24 if path.extension().map_or(false, |ext| ext == "xlsx"){25 Some(path)26 }else {27 None28 }29 })30 .count() as u64;31 let pb = ProgressBar::new(file_count);32 33 let mut is_head_writed = false;34 35 // フォルダ内の各Excelファイルに対して処理を実行36 for file in read_dir(folder_path)? {37 let file_path = file?.path();38 if let Some(extension) = file_path.extension() {39 // 拡張子がxlsxのファイルのみ処理する40 if extension == "xlsx" {41 // エクセルファイルを開く42 let mut workbook: Xlsx<_> = open_workbook(&file_path)?;43 workbook 44 .load_tables()45 .unwrap_or_else(|err| eprintln!("IO Error -> {}",err));46 47 if let Some(Ok(table)) = workbook.table_by_name("exampleTable"){48 if false == is_head_writed {49 wtr 50 .write_record(table.columns())51 .unwrap_or_else(|err| eprintln!("IO Error -> {}",err));52 is_head_writed = true;53 }54 for row in table.data().rows(){55 if "" != row[1].to_string() {56 wtr 57 .write_record(row.iter().map(|f|f.to_string()).collect::<Vec<_>>())58 .unwrap_or_else(|err| eprintln!("IO Error -> {}",err));59 }else {60 // データが空なのでskip61 }62 }63 }64 }65 }66 thread::sleep(Duration::from_millis(5));67 pb.inc(1);68 }69 wtr.flush()?;70 pb.finish_with_message("done");71 println!("作成完了!");72 Ok(())73}
補足情報(FW/ツールのバージョンなど)
[dependencies]
calamine = "0.20.0"
csv = "1.2"
indicatif = "0.15.0"

0 コメント