我在 7z 存档中有一个 100 GB 的文本文件。我可以通过读取 1 MB block (7z 将数据输出到标准输出)来找到模式 'hello'
:
Popen("7z e -so archive.7z big100gb_file.txt", stdout=PIPE)
while True:
block = proc.stdout.read(1024*1024) # 1 MB block
i += 1
...
if b'hello' in block: # omitting other details for search pattern split in consecutive blocks...
print('pattern found in block %i' % i)
...
现在我们在搜索 5 分钟后发现模式 'hello'
是,比如说,在第 23456 个 block 中,以后如何在 7z 中非常快速地访问这个 block 或行文件?
(如果可能,不将此数据保存在另一个文件/索引中)
使用7z
,如何在文件中间寻找?
注意:我已经阅读了 Indexing / random access to 7zip .7z archives 和 random seek in 7z single file archive,但这些问题不讨论具体实现。
最佳答案
原则上,可以为压缩数据建立索引。比方说,您可以选择一个未压缩数据的 block 大小,其中每个 block 的开头将是您可以开始解压缩的入口点。索引将是您将构建的单独文件或内存中的大型结构,并为每个入口点保存整个解压缩状态。您需要将所有压缩数据解压缩一次以构建索引。 block 大小的选择将平衡您希望以多快的速度访问压缩数据中的任何给定字节与索引的大小。
7z 可以使用几种不同的压缩方法(deflate、lzma2、bzip2、ppmd)。对于每种方法,实现这种随机访问需要做的事情完全不同。
此外,对于每种方法,都有比某些固定的未压缩 block 大小更好的选择入口点的地方。这样的选择将大大减少索引的大小,同时利用该方法使用的压缩数据的内部结构。
例如,bzip2 具有自然入口点,每个 bzip2 block 都没有历史记录,默认情况下每个 block 都有 900 KiB 的未压缩数据。这允许索引非常小,只需要保存压缩和未压缩的偏移量。
对于 deflate,入口点可以是 deflate block ,其中索引是所选 deflate block 的压缩和未压缩偏移量,以及每个入口点的 32K 字典。 zran.c为 deflate 压缩数据实现这样的索引。
lzma2 或 ppmd 压缩流中任意一点的解压状态都非常大。我不相信这种随机访问方法对于那些压缩方法是实用的。压缩后的数据格式需要进行修改,以便在压缩时将其分解为 block ,但会降低压缩率。
关于python - 7z文件中的随机访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72150369/