I have a binary file that stores strings like chars with a null byte for termination, which I need to read into my program. The strings look something like this:
74 65 73 74 00
("test")
This is my current code that reads one string in:
let mut pointer = (some_offset);
let mut character: u8;
let mut name: String = "".to_string();
loop{
character = read::read_u8(&path, pointer as usize);
pointer = 0x01;
if character == 0{break;}
name.push(character as char);
}
This is the read_u8 function:
pub fn read_u8(filename: &String, offset: usize) -> u8{
let mut file = std::fs::File::open(filename).unwrap();
let mut buffer = [0; 1];
file.seek(SeekFrom::Start(offset as u64)).unwrap();
file.read(&mut buffer[..]).unwrap() as u8;
return u8::from_be_bytes(buffer);
}
Now, this is quite slow. It takes around 6 seconds to read in 500 of these. Is there any way I can speed up either of these two code snippets up?
CodePudding user response:
Your read_u8()
function works fine if you're only interested in reading a single byte, but its inefficient for reading multiple bytes since the file shouldn't be closed and reopened and read calls can be buffered.
For reading nul-terminated strings, you should wrap your file in a BufReader
and use .read_until()
:
use std::fs::File;
use std::io::{BufRead, BufReader, Seek, SeekFrom};
let filename = "./test.bin";
let offset = 0x0100;
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'\0', &mut data).unwrap();
// read_until() will include the trailing '\0' unless
// it encounters EOF, just trim it off if its there.
if data.last() == Some(&0) {
data.pop();
}
let name = String::from_utf8(data);
See it on the playground.