“我是 Rust 的新手,我正在做一个项目,我需要扫描大量文件夹中的文件并将过滤后的数据保存到 JSON 文件中。我目前正在使用 Rayon 执行快速 foreach 循环在包含文件夹的“Vec”上。在循环中,我读取一个文件,过滤有用的信息并将其保存到一个文件中。
这是最终的working版本。但是我怀疑这不是最好的解决方案。
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
和更高版本。我的解决方案是在 OpenOptions
中打开一个新的 for_each
编写器。但我的问题是,我怎么能使用 file
变量而不创建新的作者?
正如 Chayim Friedman 在评论中所展示的那样,您并不真的需要为了写入它而改变
File
。这是因为 &File
实现了 Write
,反映了从多个线程写入操作系统级文件句柄完全没问题的事实。但是,这种方法有两个问题:
File::write_all()
可以一次写完所有内容。如果底层File::write()
表示只写入了一部分数据,它会发出一个新的write()
来写出其余部分。这个 write()
可能在另一个线程发出它自己的 write()
s 之后出现,导致文件中的数据交错(损坏)。File
包装到 BufWriter
中,那么该技巧将不起作用,如果您要写出大量数据,这是一个非常合理的做法。因此我建议只使用 Mutex,它解决了这两个问题(这也是像 C 和 C++ 这样的语言在幕后所做的):
let mut file = OpenOptions::new()
.write(true)
.append(true)
.open("out.json")
.unwrap();
file.write_all(b"Some data").unwrap();
// wrap file in a Mutex to use it in parallel
let file = Mutex::new(file);
folder_nas.par_iter().for_each(|_x| {
// lock the mutex to access the file
file.lock().unwrap().write_all(b"Some filtered data").unwrap();
});
// extract the original file and use it as before
let mut file = file.into_inner().unwrap();
file.write_all(b"Some data").unwrap();