由于 Rust 相对较新,我见过太多读写文件的方法。许多是某人为他们的博客想出的非常困惑的片段,我发现的 99% 的例子(甚至在 Stack Overflow 上)都来自不再有效的不稳定构建。现在 Rust 已经稳定了,什么是用于读取或写入文件的简单、可读、无 panic 的代码片段?
这是我所获得的最接近于读取文本文件的方法,但它仍然无法编译,尽管我相当确定我已经包含了我应该拥有的所有内容。这是基于我在所有地方的 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() {
|> ^^^^^
总而言之,我正在寻找的是:
- 简洁
- 可读性
- 涵盖所有可能的错误
- 不 panic
最佳答案
我在这里展示的所有功能都不会自行崩溃,但我正在使用 expect
因为我不知道哪种错误处理最适合您的应用程序。去阅读 The Rust Programming Language 的 chapter on error handling了解如何适本地处理您自己的程序中的失败。
Rust 1.26 及更高版本
如果你不想关心底层细节,有读写的单行函数。
读取文件到String
use std::fs;
fn main() {
let data = fs::read_to_string("/etc/hosts").expect("Unable to read file");
println!("{}", data);
}
将文件读取为 Vec<u8>
use std::fs;
fn main() {
let data = fs::read("/etc/hosts").expect("Unable to read file");
println!("{}", data.len());
}
写一个文件
use std::fs;
fn main() {
let data = "Some data!";
fs::write("/tmp/foo", data).expect("Unable to write file");
}
Rust 1.0 及以后版本
这些形式比分配 String
的单行函数稍微冗长一些。或 Vec
对你来说,但更强大的是你可以重用分配的数据或附加到现有对象。
读取数据
读取文件到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);
}
将文件读取为 Vec<u8>
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());
}
写一个文件
写一个文件是类似的,除了我们使用 Write
特征,我们总是写出字节。您可以转换 String
/&str
到字节 as_bytes
:
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");
}
缓冲 I/O
I felt a bit of a push from the community to use
BufReader
andBufWriter
instead of reading straight from a file
缓冲读取器(或写入器)使用缓冲区来减少 I/O 请求的数量。例如,访问磁盘一次读取 256 字节比访问磁盘 256 次效率更高。
话虽这么说,但我不认为缓冲读取器/写入器在读取整个文件时会有用。 read_to_end
似乎以较大块的形式复制数据,因此传输可能已经自然地合并为较少的 I/O 请求。
这是一个用它来阅读的例子:
use std::fs::File;
use std::io::{BufReader, Read};
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::{BufWriter, Write};
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");
}
A 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);
}
}
关于file-io - 在 Rust 1.x 中读写文件的实际方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31192956/