【问题标题】:Reading from file at different offsets using rust使用 rust 从不同偏移量的文件中读取
【发布时间】:2021-04-17 00:05:36
【问题描述】:

我正在从事一个项目,该项目涉及从不同偏移量的文件中读取不同信息。

目前,我正在使用以下代码:

    // ------------------------ SECTORS PER CLUSTER ------------------------

// starts at 13
opened_file.seek(SeekFrom::Start(13)).unwrap();
let aux: &mut [u8] = &mut [0; 1];
let _buf = opened_file.read_exact(aux);

// ------------------------ RESERVED SECTORS ------------------------

// starts at 14
opened_file.seek(SeekFrom::Start(14)).unwrap();
let aux: &mut [u8] = &mut [0; 2];
let _buf = opened_file.read_exact(aux);

但是如你所见,我每次都需要创建一个我想读取的大小的新缓冲区,我不能直接将它指定为函数的参数。

我尝试制作一个结构,但我无法制作一个包含我想要的所有不同数据的结构。例如:

    struct FileStruct {
        a1: &mut [u8] &mut [0; 1],
        a2: &mut [u8] &mut [0; 2],
    }

read_exact 方法需要哪些类型才能工作。

是否有一种更有效的方法可以从文件的不同偏移量读取信息,而无需为我想从文件中读取的每条信息重复粘贴这些代码行?某种函数/光标/向量可以轻松地围绕偏移量移动?以及将这些信息写入结构字段的方法?

提前致谢!

【问题讨论】:

    标签: file rust


    【解决方案1】:

    最简单的方法是拥有一个拥有数组的结构,然后查找并读入该结构。

    use std::io::{self, prelude::*, SeekFrom};
    
    #[derive(Debug, Clone, Default)]
    struct FileStruct {
        a1: [u8; 1],
        a2: [u8; 2],
    }
    
    fn main() -> io::Result<()> {
        let mut file_struct: FileStruct = Default::default();
        let mut opened_file = unimplemented!(); // open file somehow
        opened_file.seek(SeekFrom::Start(13))?;
        opened_file.read_exact(&mut file_struct.a1)?;
        opened_file.seek(SeekFrom::Start(14))?;
        opened_file.read_exact(&mut file_struct.a2)?;
        println!("{:?}", file_struct);
        Ok(())
    }
    

    Playground link

    这仍然是相当重复的,所以你可以创建一个seek_read 函数来减少重复:

    use std::io::{self, prelude::*, SeekFrom};
    
    #[derive(Debug, Clone, Default)]
    struct FileStruct {
        a1: [u8; 1],
        a2: [u8; 2],
    }
    
    fn seek_read(mut reader: impl Read + Seek, offset: u64, buf: &mut [u8]) -> io::Result<()> {
        reader.seek(SeekFrom::Start(offset))?;
        reader.read_exact(buf)?;
        Ok(())
    }
    
    fn main() -> io::Result<()> {
        let mut file_struct: FileStruct = Default::default();
        let mut opened_file = unimplemented!(); // open file somehow
        seek_read(&mut opened_file, 13, &mut file_struct.a1)?;
        seek_read(&mut opened_file, 14, &mut file_struct.a2)?;
        println!("{:?}", file_struct);
        Ok(())
    }
    

    Playground link

    使用宏可以进一步降低重复:

    use std::io::{self, prelude::*, SeekFrom};
    
    #[derive(Debug, Clone, Default)]
    struct FileStruct {
        a1: [u8; 1],
        a2: [u8; 2],
    }
    
    macro_rules! read_offsets {
        ($file: ident, $file_struct: ident, []) => {};
        ($file: ident, $file_struct: ident, [$offset: expr => $field: ident $(, $offsets: expr => $fields: ident)*]) => {
            $file.seek(SeekFrom::Start($offset))?;
            $file.read_exact(&mut $file_struct.$field)?;
            read_offsets!($file, $file_struct, [$($offsets => $fields),*]);
        }
    }
    
    fn main() -> io::Result<()> {
        let mut file_struct: FileStruct = Default::default();
        let mut opened_file = unimplemented!(); // open file somehow
        read_offsets!(opened_file, file_struct, [13 => a1, 14 => a2]);
        println!("{:?}", file_struct);
        Ok(())
    }
    

    Playground link

    【讨论】:

      【解决方案2】:

      这是对 Aplet123 的补充答案:您必须将字节按原样存储到结构中还不是很清楚,因此您也可以分配一个缓冲区(作为固定大小的数组)和使用正确大小的切片重用它,例如

      let mut buf = [0u8;16];
      opened_file.read_exact(&mut buf[..4])?; // will read 4 bytes
      // do thing with the first 4 bytes
      opened_file.read_exact(&mut buf[..8])?; // will read 8 bytes this time
      // etc...
      

      您也可以使用the byteorder crate,它可以让您directly read numbers or sequences of numbers。它基本上只是为您执行不依赖的“创建正确大小的堆栈缓冲区;读取;解码”。

      这特别有用,因为它看起来很像“SECTORS PER CLUSTER”应该是 u8 而“RESERVED SECTORS”应该是 u16。使用byteorder,您可以直接使用read_16()read_u8()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-28
        • 2014-07-26
        • 2012-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多