gpt4 book ai didi

rust - 是否可以在 stdin.lines() 中间执行另一次读取?

转载 作者:行者123 更新时间:2023-11-29 08:07:30 25 4
gpt4 key购买 nike

考虑以下代码:

use std::io::{self, BufRead, Read};

fn main() {
let mut stdin = io::stdin();

let mut content_length = 0;
for line_wrapped in stdin.lock().lines() {
let line = line_wrapped.unwrap();
if line == "" {
let mut buf = vec![0u8; content_length];
stdin.read_exact(&mut buf).unwrap();
print!("{:?}", buf);
}
if line.starts_with("Content-Length: ") {
content_length = line
.split("Content-Length: ")
.nth(1)
.unwrap()
.parse()
.unwrap();
}
}
}

编译器输出:

error[E0502]: cannot borrow `stdin` as mutable because it is also borrowed as immutable
--> src/main.rs:11:13
|
7 | for line_wrapped in stdin.lock().lines() {
| ----- immutable borrow occurs here
...
11 | stdin.read_exact(&mut buf).unwrap();
| ^^^^^ mutable borrow occurs here
...
22 | }
| - immutable borrow ends here

有没有一种方法可以修复错误,同时保持程序的相似结构(在 .lines() 中读取)?

最佳答案

在同一流的缓冲和非缓冲读取之间交替可能非常棘手。如果您不必为了调用 lines()lock 标准输入,用于实现 StdinLock 的内部缓冲区可能会消耗超过\n 的空行,随后的 read_exact 调用将不会在正确的位置开始。

因此您只需锁定一次,并且您必须在为您提供Lines的同一个缓冲读取器上调用read_exact,确保没有字节丢失。乍一看这似乎是不可能的:lines() 按值获取 self,所以一旦调用它,就不能调用 read_exact在同一个对象上。但是您可以使用一些技巧。

BufRead 的文档 contains这条毯子 impl:

impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B

&mut 对实现 BufRead 的事物的引用实现BufRead。因此,您可以获取 StdinLock 的临时 &mut 引用,在 that 上调用 lines(),丢弃 Lines 及时将有效负载read_exact 放入buf,然后用另一个&mut 引用和另一个 重新开始>线条

这种方法需要添加另一个循环,并带有标志 has_header 以指示是否中断外部循环。它不是很漂亮,但也许你可以使用它。

let stdin = io::stdin();
let mut stdin_buf = stdin.lock();

'record: loop {
let mut content_length = 0;
let mut has_header = false;
'header: for line_wrapped in (&mut stdin_buf).lines() {
let line = line_wrapped.unwrap();
if line.starts_with("Content-Length: ") {
content_length = line["Content-Length: ".len()..].parse().unwrap();
}
if line.is_empty() {
has_header = true;
break 'header;
}
}
if has_header {
let mut buf = vec![0u8; content_length];
stdin_buf.read_exact(&mut buf).unwrap();
println!("{:?}", buf);
} else {
break 'record;
}
}

最后一点:不清楚当 Content-Length header 不存在时会发生什么。如果您的原始代码有效,它将重用先前定义的值(无论最后一个内容长度是多少,或者第一个记录为 0)。我的版本一直使用 0。在 Rust 中习惯使用 Option 来表示可能未初始化的值,例如 content_length,因此将其初始化为 None 可能是更好的选择,如果缺少 Content-Length header 是需要检测的错误。

关于rust - 是否可以在 stdin.lines() 中间执行另一次读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50890373/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com