在標準庫中是否存在支持向數據流中「推送」字節的流類型Read
,以便隨後的讀取將在數據流中的其他字節之前首先返回所述字節?如何將字節推回到Rust中的Read實現類型?
n = stream.read(&mut buf).unwrap();
if ... {
stream.???PUT_BACK???(&buf[..n])
}
在標準庫中是否存在支持向數據流中「推送」字節的流類型Read
,以便隨後的讀取將在數據流中的其他字節之前首先返回所述字節?如何將字節推回到Rust中的Read實現類型?
n = stream.read(&mut buf).unwrap();
if ... {
stream.???PUT_BACK???(&buf[..n])
}
反過來思考問題:如何在某些情況下只讀取一些字節。然後你可以使用BufRead
特點:
use std::fs::File;
use std::io::{BufRead, BufReader};
fn main() {
let f = File::open("/etc/hosts").expect("unable to open");
let mut f = BufReader::new(f);
{
let bytes = f.fill_buf().expect("cannot read");
println!("{:?}", bytes[0]);
}
if some_condition() {
f.consume(2);
}
{
let bytes = f.fill_buf().expect("cannot read");
println!("{:?}", bytes[0]);
}
}
在您需要添加數據不是原始源部分,然後用chain
,作爲Florian Weimer shows罕見的情況下,很可能會更合適。在罕見的情況下,你可以寫你需要的東西:
use std::fs::File;
use std::io::{self, Read};
use std::cmp::min;
/// Warning: lightly tested; never shrinks
struct PushableRead<R> {
extra: Vec<u8>,
offset: usize,
inner: R,
}
impl<R> PushableRead<R>
where
R: Read,
{
fn new(inner: R) -> Self {
Self {
extra: Vec::new(),
offset: 0,
inner,
}
}
fn push(&mut self, bytes: &[u8]) {
self.extra.extend(bytes)
}
}
impl<R> Read for PushableRead<R>
where
R: Read,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let extra_bytes = self.extra.len() - self.offset;
if extra_bytes > 0 {
let to_copy = min(extra_bytes, buf.len());
let dst = &mut buf[0..to_copy];
let src = &self.extra[self.offset..self.offset + to_copy];
dst.copy_from_slice(src);
self.offset += to_copy;
Ok(to_copy)
} else {
self.inner.read(buf)
}
}
}
fn main() {
let f = File::open("/etc/hosts").expect("unable to open");
let mut f = PushableRead::new(f);
f.push(b"This is extra junk");
let mut data = Vec::new();
f.read_to_end(&mut data).expect("Unable to read");
println!("{:?}", std::str::from_utf8(&data));
}
看一看在chain
method of std::io::read
及其例子(這裏略作修改):
fn main() {
use std::io::prelude::*;
use std::fs::File;
let f1 = File::open("foo.txt").unwrap();
let f2 = File::open("bar.txt").unwrap();
let mut handle = f1.chain(f2);
let mut buffer = String::new();
handle.read_to_string(&mut buffer).unwrap();
println!("{:?}", buffer);
}
沒有辦法與原來的Read
對象要做到這一點,因爲特質根本不提供此設施。如果您需要某種形式的lookahead,您需要查看BufRead
trait或BufReader
struct,儘管它的超前支持非常有限。
是'stream'限於'Read'特性還是可以選擇更具體的類型? – the8472
只要基本的字節源可以是實現「Read」的任何對象,任何類型都是可以接受的。 – Doe