Home > Mobile >  Reading a string from a file until 0x00 fast
Reading a string from a file until 0x00 fast

Time:04-14

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.

  • Related