由于 Rust 相对较新,我见过太多读写文件的方法。许多是某人为他们的博客提出的非常混乱的片段,我发现的 99% 的示例都来自不再工作的不稳定构建。现在 Rust 已经稳定了,什么是用于读取或写入文件的简单、可读、不惊慌的代码片段?
这是我在读取文本文件方面最接近的东西,但即使我相当确定我已经包含了我应该拥有的所有内容,它仍然没有编译。这是基于我在所有地方的 Google+ 上找到的一个片段,我唯一改变的是旧BufferedReader的现在只是BufReader:
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() { |> ^^^^^
总而言之,我正在寻找的是:
我在这里展示的所有功能都不会自行恐慌,但我正在使用它,expect因为我不知道哪种错误处理最适合您的应用程序。去阅读 The Rust Programming Language 的错误处理章节,了解如何在你自己的程序中适当地处理失败。
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这些形式比为您分配 a或为您的单行函数稍微冗长Vec,但更强大的是您可以重用分配的数据或附加到现有对象。
Vec
读取文件需要两个核心部分:File和Read.
File
Read
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()); }
写一个文件是类似的,除了我们使用Writetrait 并且我们总是写出字节。您可以使用以下命令将String/转换&str为字节as_bytes:
Write
&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"); }
我觉得社区有点推动使用BufReader而BufWriter不是直接从文件中读取
BufWriter
缓冲读取器(或写入器)使用缓冲区来减少 I/O 请求的数量。例如,访问磁盘一次以读取 256 字节比访问磁盘 256 次效率更高。
话虽如此,我不相信缓冲读取器/写入器在读取整个文件时会有用。read_to_end似乎以较大的块复制数据,因此传输可能已经自然地合并为更少的 I/O 请求。
read_to_end
这是使用它进行阅读的示例:
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当您想逐行阅读时,A更有用:
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); } }