是否有一种惯用的方法来处理文件,一次处理一个字符?

这大概就是我想要的:

let mut f = io::BufReader::new(try!(fs::File::open("input.txt")));

for c in f.chars() {
    println!("Character: {}", c.unwrap());
}

Read::chars到目前为止仍然不稳定.6.0.

我考虑过使用Read::read_to_string,但文件可能很大,我不想把它全部读入内存.

推荐答案

让我们比较一下4种方法.

1. 100

您可以复制Read::chars个实现,但它标记为不稳定

错误发生位置的部分读/写的语义目前尚不清楚,可能会发生变化

因此,必须小心一些.无论如何,这似乎是最好的方法.

2. 100

flat_map个备选方案没有编译:

use std::io::{BufRead, BufReader};
use std::fs::File;

pub fn main() {
    let mut f = BufReader::new(File::open("input.txt").expect("open failed"));

    for c in f.lines().flat_map(|l| l.expect("lines failed").chars()) {
        println!("Character: {}", c);
    }
}

问题是chars从字符串中borrow ,但l.expect("lines failed")只存在于闭包中,所以编译器给出了错误borrowed value does not live long enough.

3. Nested for

这个代码

use std::io::{BufRead, BufReader};
use std::fs::File;

pub fn main() {
    let mut f = BufReader::new(File::open("input.txt").expect("open failed"));

    for line in f.lines() {
        for c in line.expect("lines failed").chars() {
            println!("Character: {}", c);
        }
    }
}

行,但它为每行保留一个字符串.此外,如果输入文件上没有换行符,整个文件将被加载到内存中.

4. 100

方法3的另一种节省内存的方法是使用Read::read_until,并使用单个字符串读取每一行:

use std::io::{BufRead, BufReader};
use std::fs::File;

pub fn main() {
    let mut f = BufReader::new(File::open("input.txt").expect("open failed"));

    let mut buf = Vec::<u8>::new();
    while f.read_until(b'\n', &mut buf).expect("read_until failed") != 0 {
        // this moves the ownership of the read data to s
        // there is no allocation
        let s = String::from_utf8(buf).expect("from_utf8 failed");
        for c in s.chars() {
            println!("Character: {}", c);
        }
        // this returns the ownership of the read data to buf
        // there is no allocation
        buf = s.into_bytes();
        buf.clear();
    }
}

Rust相关问答推荐

计算具有相邻调换且没有插入或删除的序列的距离

为什么我们不能通过指针算法将Rust原始指针指向任意地址?'

在析构赋值中使用一些现有绑定

rust 蚀生命周期 不匹配-不一定超过此处定义的生命周期

Rust ndarray:如何从索引中 Select 数组的行

装箱特性如何影响传递给它的参数的生命周期 ?(举一个非常具体的例子)

为什么比较Option<;字符串>;具有常数Option<&;str>;需要显式类型转换吗?

如何强制匹配的返回类型为()?

我们可以在 Rust 切片中使用步骤吗?

Rust 并行获取对 ndarray 的每个元素的可变引用

如何基于常量在Rust中跳过一个测试

max(ctz(x), ctz(y)) 有更快的算法吗?

在 Rust 中,我如何处理请求 javascript 的页面?

Rust 中的方法调用有什么区别?

仅在运行测试时生成调试输出

如何创建递归borrow 其父/创建者的 struct ?

为什么具有 Vec 变体的枚举没有内存开销?

为什么指定生命周期让我返回一个引用?

有没有办法隐藏类型定义?

基于名称是否存在的条件编译