首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >逐字读取锈蚀中的文件

逐字读取锈蚀中的文件
EN

Stack Overflow用户
提问于 2016-02-13 21:47:48
回答 3查看 11.2K关注 0票数 22

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

这似乎是我想要的:

代码语言:javascript
运行
复制
let mut f = io::BufReader::new(try!(fs::File::open("input.txt")));

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

但在Rust 1.6.0时,Read::chars仍然不稳定。

我考虑过使用Read::read_to_string,但是文件可能很大,我不想全部读到内存中。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-05-12 14:20:58

让我们比较四种方法。

Read::chars 1.

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

错误发生的部分读/写的语义目前还不清楚,并且可能会改变。

所以一定要小心。不管怎样,这似乎是最好的方法。

flat_map 2.

flat_map替代方案不编译:

代码语言:javascript
运行
复制
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从字符串中借用,但是l.expect("lines failed")只存在于闭包中,所以编译器给出了错误borrowed value does not live long enough

3.嵌套用于

这段代码

代码语言:javascript
运行
复制
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);
        }
    }
}

工作,但它为每一行分配一个字符串。此外,如果输入文件没有中断行,则整个文件将被加载到内存中。

BufRead::read_until 4.

与方法3相比,一个内存高效的替代方法是使用Read::read_until,并使用一个字符串读取每一行:

代码语言:javascript
运行
复制
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();
    }
}
票数 11
EN

Stack Overflow用户

发布于 2021-02-15 16:33:57

我不能使用lines(),因为我的文件可以是一个千兆字节大小的行。这是对@malbarbo的建议的一个改进,即从老版本的Rust复制Read::charsutf8 8-炭箱已经为您添加了.chars()BufRead

检查他们的存储库,看起来一次加载的字节不超过4个字节。

您的代码将与Rust删除Read::chars之前的代码相同。

代码语言:javascript
运行
复制
use std::io::stdin;
use utf8_chars::BufReadCharsExt;

fn main() {
    for c in stdin().lock().chars().map(|x| x.unwrap()) {
        println!("{}", c);
    }
}

在Cargo.toml中添加以下内容:

代码语言:javascript
运行
复制
[dependencies]
utf8-chars = "1.0.0"
票数 3
EN

Stack Overflow用户

发布于 2016-05-12 03:42:44

在这里有两个解决方案是有意义的。

首先,您可以复制Read::chars()的实现并使用它;如果/当代码稳定时,将代码移到标准库实现中将变得非常简单。

另一方面,您可以简单地逐行迭代(使用f.lines()),然后在每一行上使用line.chars()来获得字符。这有点麻烦,但肯定会成功的。

如果只想要一个循环,就可以使用flat_map()|line| line.chars()这样的lambda。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35385703

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档