1

我有一个具有以下结构的二进制文件:

+---------+--------+------+----+-------+
| 页眉 | 对象1 | 对象2 | ... | 索引 |
+---------+--------+------+----+-------+

Index是一个可变大小的向量,取决于对象的数量,并存储每个对象的文件位置。例如

vector<size_t> index;

index.push_back(ofs.tellp());
write(reinterpret_cast<char *> obj, sizeof(obj));

文件也很大(1Gb+)。

我想把索引放在标题之后,这样阅读起来会更快。我可以这样做而不必复制和写入所有对象两次吗?谢谢。

4

3 回答 3

1

当你写文件时计算你有多少个对象。

nObjects // Number of objects

然后你需要

indexSize = nObjects * sizeof(size_t);

开始写你的对象

ofs.seekp(indexSize + headerSize)

写下你所有的对象

index.push_back(ofs.tellp());
write(reinterpret_cast<char *> obj, sizeof(obj));

移动到索引的开头 ofs.seekp(headerSize);

写下你的索引

于 2012-11-29T18:34:14.230 回答
1

你有两个解决方案:

  • 为索引使用单独的文件
  • 继续基于块的设计

第一个比较明显,所以我只概述第二个:这里的问题是您的索引大小取决于您流式传输的对象数量。不必如此。

一个解决方案是跳过一定数量的空间(稍后用于索引),流式传输对象(最多 N),记录您的位置,返回索引将其写下来,然后继续下一个块(注意:这里的块不是固定大小的)。

布局示例:

- Step 1: skip index space and start streaming objects

| Header | <unused space for now> | Obj 1 | Obj 2   | O3 | ... Obj N |


- Step 2: after writing N objects write the index,
          record the offset,
          start a new chunk

| Header | I1 | ... | IN | Offset | Obj 1 | Obj 2   | O3 | ... Obj N | <unused sp

因此,您的索引被构建为一个固定大小的块 (N) 的链接列表,这些块 (N) 交错在您的存储中间。

注意:第三种解决方案是使用一个简单的 SQLite 文件并让它为您编制索引...

于 2012-11-29T19:08:52.823 回答
0

我认为答案是否定的,但如果你有低级文件系统工具并且知道如何操作你选择的文件系统,你也许可以做到这一点。

假设您使用的是旧的愚蠢 FAT,其中 FAT 表存储有关文件所在磁盘扇区的信息,然后您可以为索引分配扇区,然后修改与文件相关的 FAT 表条目以指定新的顺序磁盘上用于文件的扇区,本质上是在不重新保存整个内容的情况下重新排序。

这将如何与 NTFS、ZFS 等一起工作 - 我不知道,但如果不涉及 NTFS 结构的操作,我很确定这是不可能的。

是否有意义?

于 2012-11-29T18:21:49.550 回答