《Rust by Examples》一书提供了两个(此处相关)示例,说明如何使用
BufRead
。
他们首先给出了一个“初学者友好”的例子,然后再进行更“有效的方法”。
初学者友好的示例逐行读取文件:
use std::fs::File;
use std::io::{ self, BufRead, BufReader };
fn read_lines(filename: String) -> io::Lines<BufReader<File>> {
// Open the file in read-only mode.
let file = File::open(filename).unwrap();
// Read the file line by line, and return an iterator of the lines of the file.
return io::BufReader::new(file).lines();
}
fn main() {
// Stores the iterator of lines of the file in lines variable.
let lines = read_lines("./hosts".to_string());
// Iterate over the lines of the file, and in this case print them.
for line in lines {
println!("{}", line.unwrap());
}
}
“有效方法”的作用几乎相同:
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
fn main() {
// File hosts must exist in current path before this produces output
if let Ok(lines) = read_lines("./hosts") {
// Consumes the iterator, returns an (Optional) String
for line in lines {
if let Ok(ip) = line {
println!("{}", ip);
}
}
}
}
// The output is wrapped in a Result to allow matching on errors
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}
锈书对于后者的说法是:
此过程比在内存中创建字符串更有效,尤其是处理较大的文件时。
虽然后者稍微干净一些,但使用
if let
而不是 unwrap
,为什么返回 Result
效率更高呢?
我假设一旦我们在第二个示例中解开迭代器(在if let Ok(lines) = read_lines("./hosts")
中),从性能角度来看它应该与第一个示例相同。
那为什么会有所不同呢?
为什么第二个例子中的迭代器每次都会返回一个结果?
你是对的“初学者友好”方法的效率并不低,并且不会“在内存中创建字符串”。看来我们很多人都感到困惑。
目前至少有两个拉取请求试图解决混乱,也许您可以评论您喜欢的拉取请求:
read_to_string
而不是 BufRead
。
read_to_string
使得初学者友好的方法“效率不高”,正如#1641中的文本所暗示的那样。
read_to_string
还给出了“在内存中创建String”的真实例子。有趣的是,自从第一次提交......以来,“在内存中创建一个字符串”这句话就出现了。
...起初,该短语仅描述了一种假设的方法,效率较低...
...然后#1641以初学者友好的方法给出了一些实际代码...但是它效率丝毫不减!...
...直到 #1679 或 #1681 为止,从来没有 实际代码 展示了效率较低的方法!