在rust中读取u8字节文件并从中解析信息的最高效的方法是什么



我的问题更多地是关于我想做的操作的性能。

问题

我有一个u8 byte文件,其中我知道要从中提取的信息的字节偏移量,以及它们的字节长度。理想情况下,我希望将这些信息存储在某种对象中,以便以后使用。

前任

  • 需要信息1@字节偏移0x2C
  • 需要Info2@字节偏移0X30

我对这个问题的天真解决方案是在读取文件时偏移read_exact缓冲区,然后以可变字节长度获得我想要的信息(见下文(。

天真的解决方案

fn main() -> std::io::Result<()> {
let mut file = File::open("foo.xd")?;

// read till offset
let mut offset = [0; 0x2C];
file.read_exact(&mut offset)?;
// then get the byte of information i want 
let mut info1 = [0; 0x1];
file.read_exact(&mut info1)?;
println!("{info1:?}");
// do some kind of repeatable process for the other information
Ok(())
}

我缺乏锈蚀方面的经验,不知道在不同的偏移上反复执行这种操作是好是坏。我的直觉说不好。有人能在这里提出一个可重复的模式吗?这个模式适用于我的用例,但从性能的角度来看也是有效的?

正如@Kenny所提到的,如果你想在文件中跳大距离,你可能想使用Seek特性。

data.txt:

abcdefghijklmnopqrstuvwxyz

main.rs:

use std::{
fs::File,
io::{Read, Seek, SeekFrom},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut file = File::open("data.txt")?;
// Buffer to read into
let mut buffer = [0u8; 5];
// Read at position 10
file.seek(SeekFrom::Start(10))?;
file.read_exact(&mut buffer)?;
println!("{:?}", std::str::from_utf8(&buffer).unwrap());
// Read at position 5
file.seek(SeekFrom::Start(5))?;
file.read_exact(&mut buffer)?;
println!("{:?}", std::str::from_utf8(&buffer).unwrap());
Ok(())
}
"klmno"
"fghij"

当然,如果你的数据位于有序位置,你也可以使用相对搜索:

use std::{
fs::File,
io::{Read, Seek, SeekFrom},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut file = File::open("data.txt")?;
// Buffer to read into
let mut buffer = [0u8; 5];
// Read at position 5
file.seek(SeekFrom::Start(5))?;
file.read_exact(&mut buffer)?;
println!("{:?}", std::str::from_utf8(&buffer).unwrap());
// Read at position 12
file.seek(SeekFrom::Current(2))?;
file.read_exact(&mut buffer)?;
println!("{:?}", std::str::from_utf8(&buffer).unwrap());
Ok(())
}
"fghij"
"mnopq"

一个小短途旅行。

你可以把它包装成一个函数:

use std::{
fs::File,
io::{Read, Seek, SeekFrom},
};
fn read_at_position(f: &mut File, pos: u64, buffer: &mut [u8]) -> std::io::Result<()> {
f.seek(SeekFrom::Start(pos))?;
f.read_exact(buffer)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut file = File::open("data.txt")?;
// Buffer to read into
let mut buffer = [0u8; 5];
// Read at position 10
read_at_position(&mut file, 10, &mut buffer)?;
println!("{:?}", std::str::from_utf8(&buffer).unwrap());
// Read at position 5
read_at_position(&mut file, 5, &mut buffer)?;
println!("{:?}", std::str::from_utf8(&buffer).unwrap());
Ok(())
}

或者甚至将其作为File:的特性来实现

use std::{
fs::File,
io::{Read, Seek, SeekFrom},
};
trait ReadAtPosition {
fn read_at_position(&mut self, pos: u64, buffer: &mut [u8]) -> std::io::Result<()>;
}
impl ReadAtPosition for File {
fn read_at_position(&mut self, pos: u64, buffer: &mut [u8]) -> std::io::Result<()> {
self.seek(SeekFrom::Start(pos))?;
self.read_exact(buffer)
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut file = File::open("data.txt")?;
// Buffer to read into
let mut buffer = [0u8; 5];
// Read at position 10
file.read_at_position(10, &mut buffer)?;
println!("{:?}", std::str::from_utf8(&buffer).unwrap());
// Read at position 5
file.read_at_position(5, &mut buffer)?;
println!("{:?}", std::str::from_utf8(&buffer).unwrap());
Ok(())
}

最新更新