什么是在Rust 1.x中读写文件的事实上的方式?
随着Rust相对较新,我看到了太多的读写文件的方式。 许多人是非常杂乱的片段,有人提出他们的博客,我发现的例子(即使在堆栈溢出)的99%是来自不稳定的构build,不再工作。 既然Rust是稳定的,那么读取或写入文件的简单,可读,非恐慌的片段是什么呢?
这是我读到的文本文件中最接近的东西,但它仍然没有编译,即使我相当肯定,我已经包括了我应该有的一切。 这是基于我在Google+上发现的所有地方的一个片段,我唯一改变的是旧的BufferedReader
现在只是BufReader
:
use std::fs::File; use std::io::BufReader; use std::path::Path; fn main() { let path = Path::new("./textfile"); let mut file = BufReader::new(File::open(&path)); for line in file.lines() { println!("{}", line); } }
编译器抱怨:
error: the trait bound `std::result::Result<std::fs::File, std::io::Error>: std::io::Read` is not satisfied [--explain E0277] --> src/main.rs:7:20 |> 7 |> let mut file = BufReader::new(File::open(&path)); |> ^^^^^^^^^^^^^^ note: required by `std::io::BufReader::new` error: no method named `lines` found for type `std::io::BufReader<std::result::Result<std::fs::File, std::io::Error>>` in the current scope --> src/main.rs:8:22 |> 8 |> for line in file.lines() { |> ^^^^^
总结一下,我正在寻找的是:
- 简短
- 可读性
- 涵盖所有可能的错误
- 不恐慌
您需要两个核心部分: File
和Read
。
如果你想读一个String
一切:
use std::fs::File; use std::io::Read; fn main() { let mut data = String::new(); let mut f = File::open("/etc/hosts").expect("Unable to open file"); f.read_to_string(&mut data).expect("Unable to read string"); println!("{}", data); }
如果你想把所有的东西都看成是一组字节:
use std::fs::File; use std::io::Read; fn main() { let mut data = Vec::new(); let mut f = File::open("/etc/hosts").expect("Unable to open file"); f.read_to_end(&mut data).expect("Unable to read data"); println!("{}", data.len()); }
没有一个function自己恐慌,但我使用expect
因为我不知道什么样的error handling将最适合您的应用程序。
这些比为你分配一个String
或者Vec
假设版本稍微冗长些,但是更强大,因为你可以重用分配的数据或者追加到一个已经存在的对象。 写一个小的包装器,为你分配的对象是微不足道的,未来可能是一个符合人体工程学的添加。
写入文件是一样的,除了它总是以字节完成的。 您可以使用as_bytes
将String
/ &str
转换为字节:
use std::fs::File; use std::io::Write; fn main() { let data = "Some data!"; let mut f = File::create("/tmp/foo").expect("Unable to create file"); f.write_all(data.as_bytes()).expect("Unable to write data"); }
我感受到来自社区的推动,使用
BufReader
和BufWriter
而不是直接从文件中读取
缓冲读取器(或写入器)使用缓冲区来减lessIO请求的数量。 例如,一次访问磁盘读取256个字节而不是访问磁盘256次效率更高。
这就是说,我不相信读取整个文件时缓冲的读写器是有用的。 read_to_end
似乎以较大的块复制数据,所以传输可能已经自然地合并成较less的IO请求。
这里有一个使用它的例子:
use std::fs::File; use std::io::{Read, BufReader}; fn main() { let mut data = String::new(); let f = File::open("/etc/hosts").expect("Unable to open file"); let mut br = BufReader::new(f); br.read_to_string(&mut data).expect("Unable to read string"); println!("{}", data); }
而写作:
use std::fs::File; use std::io::{Write, BufWriter}; fn main() { let data = "Some data!"; let f = File::create("/tmp/foo").expect("Unable to create file"); let mut f = BufWriter::new(f); f.write_all(data.as_bytes()).expect("Unable to write data"); }
当你想逐行阅读时, BufReader
更有用:
use std::fs::File; use std::io::{BufRead, BufReader}; fn main() { let f = File::open("/etc/hosts").expect("Unable to open file"); let f = BufReader::new(f); for line in f.lines() { let line = line.expect("Unable to read line"); println!("Line: {}", line); } }