微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 rust 从不同偏移量的文件中读取

如何解决使用 rust 从不同偏移量的文件中读取

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

目前,我使用以下代码

    // ------------------------ 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 方法需要哪些类型才能工作。

有没有更有效的方法可以从文件的不同偏移量读取信息,而不必为我想从文件中读取的每条信息重复复制粘贴这些代码行?某种功能/光标/矢量可以轻松地在偏移量周围移动?以及将这些信息写入结构字段的方法

提前致谢!

解决方法

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

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,}

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,}

macro_rules! read_offsets {
    ($file: ident,$file_struct: ident,[]) => {};
    ($file: 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

,

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

{% load static %}
<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="{% static 'css/style.css' %}">
    </head>
    <body>
            <section class="content">
                {% block content %}
                {% endblock %}
            </section>
    </body>
</html>

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

这特别有用,因为它看起来很像“每个集群的扇区”应该是 u8,而“保留扇区”应该是 u16。使用 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... ,您可以直接 byteorderread_16()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。