【问题标题】:How can I stop a BufReader from reading in Rust when using read_until()?使用 read_until() 时如何阻止 BufReader 在 Rust 中读取?
【发布时间】:2018-10-17 02:36:58
【问题描述】:

我正在尝试使用BufReader 加载一堆数据,然后使用read_until() 扫描数据。但是,我很难辨别read_until() 何时到达 EOF 并且我的代码再次回到数据的开头,从而创建了一个无限循环。当read_until() 到达 EOF 时,我需要停止阅读。我怎样才能在 Rust 中做到这一点?

这是我目前所拥有的:

use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::str;

fn main() -> std::io::Result<()> {
    let f1 = File::open("foo.txt")?;
    let mut reader = BufReader::new(f1);
    let mut byte_vec: Vec<u8> = Vec::new();
    loop {
        let my_bytes = reader.read_until(b'\n', &mut byte_vec);
        let is_valid_utf8 = str::from_utf8(&byte_vec);

        match is_valid_utf8 {
            Ok(the_str) => println!("{} is a valid UTF-8 String", the_str),
            Err(err) => println!("Error: {}", err),
        }
    }
    Ok(())
}

foo.txt 只有几行示例文本。代码将永远循环回到文件的开头。

【问题讨论】:

  • 1.为什么不使用 read_line ? 2. 阅读文档 3. 阅读警告
  • 1.因为 read_line() 假设数据可以被解析为 utf8 并且我不能在我的代码中做出这个假设。 2. 特定领域的文档将很有用,而不仅仅是“阅读文档”——这与我的问题一样无用,您显然是在呼唤。理论上,每个 SO 问题都可以通过“阅读文档”来回答。来吧伙计。
  • @Stargateur 在看到This function will read bytes from the underlying stream until the newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes up to, and including, the delimiter (if found) will be appended to buf. 之后,这意味着我必须扫描每个输入组的EOF?因此,必须有一个更有效的解决方案。顺便说一句,我在问之前确实读过。
  • EOF 不是一个值。这是一种状态。在缓冲区中搜索它是没有意义的,它不作为值存在。

标签: io rust bufferedreader


【解决方案1】:

检查编译器给你的警告,这就是他们在那里的原因!

warning: unreachable expression
  --> src/lib.rs:16:5
   |
16 |     Ok(())
   |     ^^^^^^
   |
   = note: #[warn(unreachable_code)] on by default

warning: unused variable: `my_bytes`
 --> src/lib.rs:8:13
  |
8 |         let my_bytes = reader.read_until(b'\n', &mut byte_vec);
  |             ^^^^^^^^ help: consider using `_my_bytes` instead
  |
  = note: #[warn(unused_variables)] on by default

编译器告诉你

  1. 你的循环永远不会退出——那是你的无限循环。
  2. 您没有使用read_until 的返回值。

这两件事是相关的。检查read_until 的文档,强调我的:

将所有字节读入buf,直到到达分隔符字节或EOF。

[...]

如果成功,此函数将返回读取的总字节数。

使用值:

let my_bytes = reader.read_until(b'\n', &mut byte_vec)?;
if my_bytes == 0 { break };

继续阅读文档,强调我的:

所有字节(包括分隔符)(如果找到)将被附加到buf

您的byte_vec 将继续累积之前的每一行。这就是为什么您认为BufReader 正在返回到输入的开头。你可能希望在每次循环迭代结束时clear它。

另见:

【讨论】:

  • 谢谢shep,但我有一个问题-如果EOF位于行尾怎么办?读取的字节数将超过 0。这是我的困惑点。有意义吗?
  • @the_endian 很好,这取决于你想做什么。如果字符串 must 以换行符结尾,那么您必须以某种方式检查这一点,例如确保读取的最后一个字节是换行符(if byte_vec.last() != Some(&amp;b'\n') { continue } 是一种简单的方法)。大多数情况下,您希望将 EOF 视为换行符,然后您无需执行任何操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-09
相关资源
最近更新 更多