実現したいこと
ここに実現したいことを箇条書きで書いてください。
- フォルダ内の特定の拡張子ファイルに対して処理を行う
- どのくらいのファイル数があり、どのくらいの数を処理したのか表示をしたい
前提
勉強を兼ねて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 // データが空なのでskip 51 } 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 None 28 } 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 // データが空なのでskip 61 } 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"
回答1件
あなたの回答
tips
プレビュー