I'm looking to read a file until the end of the data (Note the true EOF; a literal sequence _eof), but have found trouble defining more than a single byte using read_until. Right now it stops prematurely due to the presence of underscores preceding this, but does read and output as expected otherwise:
use hex::ToHex;
use std::fs::File;
use std::io::{BufRead, BufReader, Seek, SeekFrom};
fn main() {
let filename = "./test.bin";
let offset = 0xD2F0;
// let eof = "\x5f\x65\x6f\x66";
let file = File::open(filename).unwrap();
let mut file = BufReader::new(file);
let mut data = Vec::new();
file.seek(SeekFrom::Start(offset)).unwrap();
file.read_until(b'\x5f', &mut data).unwrap();
println!(
"{:#?}",
data.encode_hex::<String>(),);
}
Is there a more sensible way to accomplish this? I've tried altering read_until in a few different fashions only to find it's looking for a single byte, but feel I'm approaching the issue in the wrong way.
This is a good start, you just have to check the next characters are what you need, and if not, keep reading.
use std::fs::File;
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom};
fn main() {
let filename = "./test.bin";
let offset = 0xD2F0;
let eof = b"\x5f\x65\x6f\x66";
let file = File::open(filename).unwrap();
let mut file = BufReader::new(file);
let mut data = Vec::new();
file.seek(SeekFrom::Start(offset)).unwrap();
loop {
file.read_until(eof[0], &mut data).unwrap();
let mut buf = [0; 3];
file.read_exact(&mut buf).unwrap();
data.extend_from_slice(&buf);
if &buf == &eof[1..] {
break;
}
}
println!("{:#?}", data);
}
Or you can use BufRead::fill_buf, BufRead::consume, and memchr directly.
use std::fs::File;
use std::io::{BufRead, BufReader, Seek, SeekFrom};
fn main() {
let filename = "./test.bin";
let offset = 0xD2F0;
let eof = b"\x5f\x65\x6f\x66";
let file = File::open(filename).unwrap();
let mut file = BufReader::new(file);
let mut data = Vec::new();
file.seek(SeekFrom::Start(offset)).unwrap();
let finder = memchr::memmem::Finder::new(eof);
loop {
let buf = file.fill_buf().unwrap();
if let Some(i) = finder.find(buf) {
data.extend_from_slice(&buf[..i + eof.len()]);
file.consume(i + eof.len());
break;
}
data.extend_from_slice(buf);
let len = buf.len();
file.consume(len);
}
println!("{:#?}", data);
}
This is perfect, thank you!! And thank you for the explanation of each option; that was where I felt stuck the most. This is my first venture into Rust and feel much more assured with your break down.