Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File 以固定大小的块读取二进制文件并将所有这些块存储到Vec中的正确方法是什么?_File_Rust_Binary - Fatal编程技术网

File 以固定大小的块读取二进制文件并将所有这些块存储到Vec中的正确方法是什么?

File 以固定大小的块读取二进制文件并将所有这些块存储到Vec中的正确方法是什么?,file,rust,binary,File,Rust,Binary,我在打开文件时遇到问题。大多数示例将文件读入字符串,或将整个文件读入Vec。我需要的是将文件读入固定大小的块,并将这些块存储到块的数组(Vec)中 例如,我有一个名为my_file的文件,大小正好为64 KB,我希望以16KB的块读取它,因此我将得到一个大小为4的Vec,其中每个元素是另一个大小为16KB(0x4000字节)的Vec 在阅读了文档并检查了其他堆栈溢出的答案后,我得出了如下结论: 让mut file=std::fs::file::open(“我的文件”)?; //…在此情况下,计算

我在打开文件时遇到问题。大多数示例将文件读入
字符串
,或将整个文件读入
Vec
。我需要的是将文件读入固定大小的块,并将这些块存储到块的数组(
Vec
)中

例如,我有一个名为
my_file
的文件,大小正好为64 KB,我希望以16KB的块读取它,因此我将得到一个大小为4的
Vec
,其中每个元素是另一个大小为16KB(0x4000字节)的
Vec

在阅读了文档并检查了其他堆栈溢出的答案后,我得出了如下结论:

让mut file=std::fs::file::open(“我的文件”)?;
//…在此情况下,计算块4的数量
让list of_chunks=Vec::new();
对于0中的块..块的数量{
让mut数据:[u8;0x4000]=[0;0x4000];
读取(&mut数据[…])?;
列出\u块的\u。push(data.to\u vec());
}
虽然这看起来很好,但看起来有点复杂。我读到:

  • 对于每个迭代,在堆栈上创建一个新数组
  • 将区块读入数组
  • 将数组内容复制到新的
    Vec
    中,然后
    Vec
    移动到
    块列表中
我不确定它是否是惯用的或甚至可能的,但我更喜欢这样:

  • 使用
    num\u chunk
    元素创建一个
    Vec
    ,其中每个元素是另一个大小为16KB的
    Vec
  • 将文件块直接读入正确的
    Vec
没有复制,我们确保在读取文件之前分配内存

这种方法可行吗?还是有更好的常规/惯用/正确的方法? 我想知道
Vec
是否是解决此问题的正确类型。我的意思是,读取文件后,我不需要数组增长。

直接高效地读取到
Vec
。如果要将其分块,请将其与组合,以限制
read\u to\u end
将读取的字节数

例如:

让mut file=std::fs::file::open(“您的_文件”)?;
让mut list_of_chunks=Vec::new();
让chunk_size=0x4000;
环路{
让mut chunk=Vec::具有_容量(chunk_大小);
设n=file.by_ref().take(chunk_大小为u64)。将_读取到_end(&mut chunk)?;
如果n==0{break;}
列出组块的组块。推送(组块);
如果n

最后一个
if
是不必要的,但它阻止了额外的
read
调用:如果
read\u to\u end
读取的字节数小于请求的字节数,我们可以期望下一个
read
什么也不读取,因为我们到达了文件的末尾。

我认为最惯用的方法是使用迭代器。以下代码(自由灵感来源):

  • 通过使用泛型类型处理许多用例
  • 将使用预先分配的向量
  • 隐藏副作用
  • 避免复制数据两次
使用std::io:{self,Read,Seek,SeekFrom};
结构块{
读:R,
大小:usize,
提示:(usize,Option),
}
impl块{
新发布(读:R,大小:usize)->Self{
自我{
阅读
大小,
提示:(0,无),
}
}
pub fn from_seek(mut read:R,size:usize)->io::Result
哪里
R:Seek,
{
让old_pos=read.seek(参见from::Current(0))?;
设len=read.seek(SeekFrom::End(0))?;
让rest=(len-old_pos)作为usize;//len总是>=old_pos,但它们是u64
如果休息!=0{
read.seek(参见from::Start(old_pos))?;
}
设min=rest/size+如果rest%size!=0{1}否则{0};
好(自我){
阅读
大小,
提示:(min,None),//这可能是错的,我不确定
})
}
//如果您想尝试从错误中恢复,这可能很有用
将fn发布到内部(自我)->R{
自述
}
}
块的impl迭代器
哪里
R:读一下,
{
类型Item=io::Result;
fn下一步(&mut self)->选项{
让mut chunk=Vec::具有_容量(self.size);
匹配自我
阅读
.by_ref()
.take(chunk.capacity()作为u64)
.read_to_end(&mut chunk)
{
Ok(n)=>{
如果n!=0{
一些(好的(块))
}否则{
没有一个
}
}
Err(e)=>一些(Err(e)),
}
}
fn大小提示(&self)->(使用,选项){
自我暗示
}
}
特点ReadPlus:阅读{
fn块(自身,大小:usize)->块
哪里
自我:大小,
{
块::新建(自身,大小)
}
}
T的impl ReadPlus,其中T:Read{}
fn main()->io::Result{
让file=std::fs::file::open(“src/main.rs”)?;
让iter=Chunks::from_seek(文件,0xFF);//替换为0xFF要测试的任何内容
println!(“{:?}”,iter.size_hint());
//这个迭代器可能永远返回Err。请小心,将其收集到结果中
让chunks=iter.collect::()?;
println!(“{:?},{:?}”,chunks.len(),chunks.capacity());
好(())
}

是否需要同时在内存中存储所有块?如果没有,你可以分配一个缓冲区并在每次迭代中重用它。为什么你认为拥有一个
Vec
会比拥有一个
Vec
好呢?@Shepmaster我知道不是这样的。我只想做一些类似于
list\u of \u chunk[chunk\u number][offset]
的事情,而不是调用一个进行数学运算的函数:
buffer[chunk\u number*size\u of \u chunk+offset]
。在第一种方法中,一旦加载了所有内容,我甚至不需要使用
size\u of_chunk
我不知道的
Read::take
。即使我在文档中看到了它,也很难意识到它是为了限制读到最后。无论如何