由于Rust相对较新,我看到了太多的文件阅读和编写方式。许多人为他们的博客提出了非常混乱的片段,我发现的99%的例子(即使在Stack Overflow上)来自不稳定的构建,不再有效。现在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() {
|> ^^^^^
总结一下,我正在寻找的是:
答案 0 :(得分:123)
我在这里展示的所有功能都没有自己恐慌,但我使用的是//n:field[@name='a']
,因为我不知道哪种错误处理最适合您的应用程序。阅读 The Rust Programming Language 的chapter on error handling,了解如何正确处理自己程序中的失败。
如果您不想关注底层细节,可以使用单行函数进行读写。
expect
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");
}
或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>
写一个文件是类似的,除了我们使用Write
特征,我们总是写出字节。您可以使用as_bytes
将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());
}
/ 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
而不是直接从文件中阅读
缓冲读取器(或写入器)使用缓冲区来减少I / O请求的数量。例如,访问磁盘一次读取256个字节而不是访问磁盘256次效率更高。
话虽这么说,我不相信缓冲读写器在阅读整个文件时会有用。 read_to_end
似乎以稍微大块的方式复制数据,因此传输可能已经自然地合并为更少的I / O请求。
以下是使用它进行阅读的示例:
BufWriter
写作:
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");
}
更有用:
BufReader
答案 1 :(得分:2)
对于正在写入文件的任何人,公认的答案是好的,但如果您需要附加到文件,则必须改用 OpenOptions 结构:
use std::fs::OpenOptions;
fn main() {
let data = "Some data!\n";
let mut f = OpenOptions::new()
.append(true)
.create(true) // Optionally create the file if it doesn't already exist
.open("/tmp/foo")
.expect("Unable to open file");
f.write_all(data.as_bytes()).expect("Unable to write data");
}
缓冲写入仍然以相同的方式工作:
use std::io::{BufWriter, Write};
use std::fs::OpenOptions;
fn main() {
let data = "Some data!\n";
let f = OpenOptions::new()
.append(true)
.open("/tmp/foo")
.expect("Unable to open file");
let mut f = BufWriter::new(f);
f.write_all(data.as_bytes()).expect("Unable to write data");
}
答案 2 :(得分:2)
通过使用 Buffered I/O
可以复制的文件大小大于实际内存。
use std::fs::{File, OpenOptions};
use std::io::{BufReader, BufWriter, Write, BufRead};
fn main() {
let read = File::open(r#"E:\1.xls"#);
let write = OpenOptions::new().write(true).create(true).open(r#"E:\2.xls"#);
let mut reader = BufReader::new(read.unwrap());
let mut writer = BufWriter::new(write.unwrap());
let mut length = 1;
while length > 0 {
let buffer = reader.fill_buf().unwrap();
writer.write(buffer);
length = buffer.len();
reader.consume(length);
}
}