“我是Rust的新手,我正在做一個項目,需要掃描大量文件夾中的文件,并將過濾后的數(shù)據(jù)保存到JSON文件中。我目前正在使用Rayon對包含文件夾的‘Vec’執(zhí)行快速foreach循環(huán)。在循環(huán)中,我讀取一個文件,過濾有用的信息,并將其保存到一個文件中。
這是最終的工作版本。然而,我懷疑這不是最好的解決方案。
fn main() {
// ...
// Imagine this is full of data
let mut folder_nas: Vec<FolderNAS> = Vec::new();
// Open a out.json file to store the results in append mode
let mut file = OpenOptions::new()
.write(true)
.append(true)
.open(FILENAME)
.unwrap();
file.write_all("Some data").unwrap();
folder_nas.par_iter().for_each(|x| {
let mut file_iterator = OpenOptions::new()
.write(true)
.append(true)
.open(FILENAME)
.unwrap();
file_iterator
.write_all("Some filtered data")
.unwrap();
});
file.write_all("Some data").unwrap();
}
起初,來自其他語言的我嘗試過這個。
fn main() {
// ...
// Imagine this is full of data
let mut folder_nas: Vec<FolderNAS> = Vec::new();
// Open a out.json file to store the results in append mode
let mut file = OpenOptions::new()
.write(true)
.append(true)
.open(FILENAME)
.unwrap();
file.write_all("Some data").unwrap();
folder_nas.par_iter().for_each(|x| {
// Notice the name difference
file.write_all("Some filtered data")
.unwrap();
});
file.write_all("Some data").unwrap();
}
這種方法最終給了我一個錯誤,因為file
變量在for_each
及更高版本中使用。我的解決方案是在for_each
中打開一個新的OpenOptions
編寫器。但我的問題是,我如何使用file
變量而不創(chuàng)建新的編寫器?
正如Chayim Friedman在評論中所展示的那樣,你真的不需要為了寫入
File
而對其進行變異。這是因為&File
實現(xiàn)了Write
,反映了這樣一個事實,即從多個threads寫入OS-level文件句柄是完全可以的。然而,這種方法存在兩個問題:File::write_all()
能夠一口氣寫出所有內(nèi)容。如果基礎(chǔ)File::write()
指示只寫入了數(shù)據(jù)的一部分,它將發(fā)出一個新的write()
來寫出其余的數(shù)據(jù)。這個write()
可能是在另一個thread發(fā)出自己的write()
之后發(fā)生的,導(dǎo)致文件中的數(shù)據(jù)交錯(損壞)。File
打包成BufWriter
,那么這個技巧就行不通了。如果你要寫出non-trivial量的數(shù)據(jù),這是一件非常合理的事情。因此,我建議只使用Mutex,它可以解決這兩個問題(這也是像C和C++這樣的語言在后臺所做的):
Playground