Given an ordinary file, the task is to read the file in chunks, but all chunks except the last must be of BLOCK_SIZE
. I would like to know the best way to do this.
How I can put it together, I have here a first variant, which seems unreliable under the circumstance that the therein mentioned assertion cannot be fulfilled.
use std::{io, io::Read, fs::File};
const BLOCK_SIZE: usize = 0x10000;
fn process_file(file: &mut File, callback: &mut dyn FnMut(&[u8]))
-> io::Result<()>
{
let mut buffer: [u8; BLOCK_SIZE] = [0; BLOCK_SIZE];
let mut last = false;
loop {
let n = file.read(&mut buffer)?;
if n == 0 {break;}
if n < BLOCK_SIZE {
assert!(last == false);
last = true;
}
callback(&buffer[..n]);
}
Ok(())
}
fn main() -> io::Result<()> {
let argv: Vec<String> = std::env::args().collect();
let mut file = File::open(&argv[1])?;
process_file(&mut file, &mut |data| {
println!("{}",data.len());
})?;
Ok(())
}
And here is a second variant, which seems rather reliable to me but is not streamable:
fn process_file(file: &mut File, callback: &mut dyn FnMut(&[u8]))
-> io::Result<()>
{
let len = file.metadata()?.len();
let count = len/(BLOCK_SIZE as u64);
let rem = (len%(BLOCK_SIZE as u64)) as usize;
let mut buffer: [u8; BLOCK_SIZE] = [0; BLOCK_SIZE];
for _ in 0..count {
file.read_exact(&mut buffer)?;
callback(&buffer);
}
if rem != 0 {
file.read_exact(&mut buffer[..rem])?;
callback(&buffer[..rem]);
}
Ok(())
}