我的问题更多地是关于我想做的操作的性能。
问题
我有一个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(())
}