我有一个具有以下结构的二进制文件:
+ --------- + ------- + ------ + ---- + ------- +
|标题| Obj1 | Obj2 | ...... |指数|
+ --------- + ------- + ------ + ---- + ------- +
Index
是一个可变大小的向量,具体取决于对象的数量,并存储每个对象的文件位置。 E.g。
vector<size_t> index;
index.push_back(ofs.tellp());
write(reinterpret_cast<char *> obj, sizeof(obj));
文件也很大(1Gb +)。
我想把索引放在标题之后,所以阅读速度更快。我可以这样做而无需复制和写入所有对象两次吗?感谢。
答案 0 :(得分: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(头信息长度);
写下你的索引
答案 1 :(得分: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)的链接列表。
注意:第三个解决方案是使用一个简单的SQLite文件并让它为你索引......
答案 2 :(得分:0)
我认为答案是肯定的,但是如果你有低级文件系统工具并且知道如何操作你选择的文件系统,你可能会这样做。
说,您正在使用旧的愚蠢FAT,其中FAT表存储有关文件所在磁盘扇区的信息,然后您可以为索引分配扇区,然后修改与您的文件相关的FAT表条目以指定磁盘上扇区的新顺序,基本上是重新排序而不需要重新整理。
如何使用NTFS,ZFS等 - 我不知道,但是如果不操纵NTFS结构,我很确定这是不可能的。
有意义吗?