7z文件的随机访问

3

我有一个被压缩为7z格式的100GB文本文件。我可以通过以1MB块的方式读取(7z将数据输出到stdout)来查找其中的模式'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)
    ...

现在我们已经找到了模式'hello',假设它在第23456个块中,在7z文件内如何快速访问这个块或行?

(如果可能的话,不要将此数据保存在另一个文件/索引中)

使用7z,如何在文件中间进行查找?

注意:我已经阅读了Indexing / random access to 7zip .7z archivesrandom seek in 7z single file archive,但这些问题没有讨论具体实现。


@TDG,一个.7z文件肯定有头部和文件表格在文件末尾,所以我几乎可以确定我们不能像这样简单地在中间寻找。 - Basj
1个回答

5
原则上,可以构建一个索引来压缩数据。您可以选择一个未压缩数据的块大小,其中每个块的开头将是一个入口点,您可以从这里开始解压缩。索引将是单独的文件或大型内存结构,您需要构建整个解压缩状态的每个入口点。您需要一次性解压缩所有压缩数据以构建索引。块大小的选择将是希望快速访问压缩数据中任何给定字节与索引大小之间的平衡。
7z可以使用几种不同的压缩方法(deflate,lzma2,bzip2,ppmd)。要实现此类随机访问,对于每种方法,您需要完全不同的操作。
此外,对于每种方法,选择入口点的更好位置比某些固定的未压缩块大小更好。这样的选择将大大减小索引的大小,利用了该方法使用的压缩数据的内部结构。
例如,bzip2在每个bzip2块中都有没有历史记录的自然入口点,默认情况下每个块具有900 KiB的未压缩数据。这使得索引可以非常小,只需要保存压缩和未压缩偏移量即可。
对于deflate压缩,入口点可以是deflate块,在该块中,索引为所选deflate块的压缩和未压缩偏移量,并且每个入口点都有32K字典。 zran.c实现了这种用于deflate压缩数据的索引。
在lzma2或ppmd压缩流中的任何点上,解压状态都非常大。我认为这样的随机访问方法对于这些压缩方法来说可能不切实际。压缩数据格式需要在压缩时被修改,以将其分成块,但这会损失一定的压缩比率。

如果我们不需要精确的索引/不需要准确的查找位置,一个包含单个.txt文件的.7z文件是否可以在大约100 GB的.7z文件的中间开始解压缩?假设我们不关心解压缩是否在49-100 GB或51-100GB范围内完成,但我们想要的是“在7z文件的第二半部分大致搜索此模式”。如何做到这一点?通过查看7z头,我们能否找到块大小,并知道例如压缩“状态”从文件偏移开始,比如说49 500 010 128? - Basj
1
不行。在第一次通常生成的压缩数据中间开始解压是不可能的,无论你从哪里开始。你需要做以下两种选择之一:a)特别准备压缩数据以具有无历史记录的入口点,或者b)将整个压缩数据解压一次以准备上述索引,这将允许后续的解压从索引点开始。 - Mark Adler
你知道@MarkAdler如何使用7z.exe处理.7z LZMA2文件吗?我可以在整个文件上运行第一遍,并记录索引文件偏移量,其中状态从头开始(不需要历史记录)。您认为这样的偏移点是否总是存在?是否有一个命令行7z.exe ...可以帮助解决这个问题? - Basj
不,这样没有历史记录的偏移点是不存在的。你需要编写自己的软件来创建这样的 .7z 文件。 - Mark Adler
如您所建议的,如何在给定点备份压缩状态并在以后重复使用它们?7z.exe是否可以使用特殊参数提供“压缩状态”@MarkAdler? - Basj
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接