如果 BufReader 接管了流,那么我该如何在其上读取和写入行?

23

我希望能够从TCPStream中读取一行,再写入另一行,然后重复执行。问题在于BufReader::new占用了我的TCPStream变量:

let stream = ...; // TCPStream

let reader = BufReader::new(stream); // moved its value

// can't use stream here anymore

这个问题有什么简单的解决方案吗?

重复的问题,参见 http://stackoverflow.com/questions/33114619/access-to-components-of-a-read-wrapped-by-take-or-chain 或者 https://dev59.com/VY3da4cB1Zd3GeqPwCuQ#31503269。 - Shepmaster
2个回答

30

解决方案:使用引用。

let mut stream = ...;
let reader = BufReader::new(&stream);
let writer = BufWriter::new(&stream);

解释

如果我们仔细研究BufReader::new,我们会发现它接受一个类型为R的参数inner,其中R只是实现了Read的任何类型:

impl<R: Read> BufReader<R> {
    pub fn new(inner: R) -> BufReader<R> { ... }
}

然后我们看一下 Read 的实现代码:

impl<'a> Read for &'a TcpStream

因此,我们只需将引用传递给new函数,就像这样:

let reader = BufReader::new(&stream);

我们将对 BufWriterWrite 采取相同的做法,并将看到确实存在这种实现:

impl<'a> Write for &'a TcpStream

因此,我们可以再次使用不可变引用来创建BufWriter


对于那些没有为引用实现Read和Write的板条箱,例如serialport,您可以使用bufstream - a544jh

5
您有几种选择:
  • 不使用BufReader
  • 使用get_mut暂时借用BufReader的流
  • 完全丢弃BufReader并使用into_inner恢复流
我个人建议,除非您真的需要缓冲输入,否则不要使用BufReader; 对于单行输入,这似乎不值得。
否则,如果您已经完成了缓冲,您可以恢复底层流,如果没有,您可以暂时缓冲它。 注意请注意,BufReader会缓冲读取,因此当您借用/恢复内部流时,会短路缓冲数据;对于读取来说这是个问题,在您的情况下(写入)应该没问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接