How to read a specific number of bytes from a stream?
Solution 1:
Since Rust 1.6, Read::read_exact
can be used to do this. If bytes_to_read
is the number of bytes you need to read, possibly determined at runtime, and reader
is the stream to read from:
let mut buf = vec![0u8; bytes_to_read];
reader.read_exact(&mut buf)?;
The part that wasn't clear to me from the read_exact
documentation was that the target buffer can be a dynamically-allocated Vec
.
Thanks to the Rust Gitter community for pointing me to this solution.
Solution 2:
It sounds like you want Read::take
and Read::read_to_end
.
This will allow you to read data into a &mut Vec<u8>
, which is useful when you want to reuse an existing buffer or don't have an appropriately sized slice already. This allows you to avoid initializing the data with dummy values before overwriting them with the newly-read information:
use std::{
io::{prelude::*, BufReader},
str,
};
fn read_n<R>(reader: R, bytes_to_read: u64) -> Vec<u8>
where
R: Read,
{
let mut buf = vec![];
let mut chunk = reader.take(bytes_to_read);
// Do appropriate error handling for your situation
// Maybe it's OK if you didn't read enough bytes?
let n = chunk.read_to_end(&mut buf).expect("Didn't read enough");
assert_eq!(bytes_to_read as usize, n);
buf
}
fn main() {
let input_data = b"hello world";
let mut reader = BufReader::new(&input_data[..]);
let first = read_n(&mut reader, 5);
let _ = read_n(&mut reader, 1);
let second = read_n(&mut reader, 5);
println!(
"{:?}, {:?}",
str::from_utf8(&first),
str::from_utf8(&second)
);
}
If you are worried that Read::take
consumes the reader by reference, note that take
comes from Read
and Read
is implemented for any mutable reference to a type that implements Read
. You can also use Read::by_ref
to create this mutable reference.
See also:
- Whats the idiomatic way to reference BufReader/BufWriter when passing it between functions?
- Why does Iterator::take_while take ownership of the iterator?