read_lines
一种朴素的方法
对于一个初学者来说,这可能是一个从文件中读取行的合理的第一种实现方法。
由于方法lines()
返回一个迭代器,该迭代器迭代文件中的行,我们也可以内联执行一个 map 操作并收集结果,从而产生一个更简洁流畅的表达式。
请注意,在上面的两个示例中,我们必须将从lines()
返回的&str
引用转换为拥有所有权的类型String
,分别使用.to_string()
和String::from
。
一种更有效的方法
在这里,我们将打开的File
的所有权传递给一个 BufReader
结构体。 BufReader
使用一个内部缓冲区来减少中间分配。
我们还更新了read_lines
来返回一个迭代器,而不是为每一行在内存中分配新的String
对象。
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
fn main() {
// File hosts.txt must exist in the current path
if let Ok(lines) = read_lines("./hosts.txt") {
// Consumes the iterator, returns an (Optional) String
for line in lines.map_while(Result::ok) {
println!("{}", line);
}
}
}
// 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())
}
运行此程序只是单独打印这些行。
$ echo -e "127.0.0.1\n192.168.0.1\n" > hosts.txt
$ rustc read_lines.rs && ./read_lines
127.0.0.1
192.168.0.1
(请注意,由于File::open
期望一个通用的AsRef<Path>
作为参数,我们使用相同的通用约束定义了我们的通用read_lines()
方法,使用了where
关键字。)
这个过程比在内存中创建一个包含文件所有内容的String
更有效。当处理较大的文件时,这尤其会导致性能问题。