压缩格式对档案内的随机访问有很好的支持?

时间:2009-01-09 22:29:45

标签: compression gzip archive zlib random-access

这类似于previous question,但那里的答案不能满足我的需求,我的问题略有不同:

我目前对包含排序数据的一些非常大的文件使用gzip压缩。当文件未被压缩时,二进制搜索是一种方便有效的方式,可以支持在排序数据中寻找位置。

但是当文件被压缩时,事情变得棘手。我最近发现了zlibZ_FULL_FLUSH选项,可以在压缩过程中使用它来在压缩输出中插入“同步点”(inflateSync()然后可以开始从文件)。这没关系,虽然我已经拥有的文件必须重新压缩才能添加这个功能(奇怪的是gzip没有这个选项,但是如果必须,我愿意编写自己的压缩程序)

one source似乎即使Z_FULL_FLUSH也不是一个完美的解决方案......不仅所有gzip档案都不支持它,而且在档案中检测同步点的想法可能会产生错误正数(或者与同步点的幻数重合,或者由于Z_SYNC_FLUSH也产生同步点,但它们不能用于随机访问)。

有更好的解决方案吗?如果可能的话,我想避免使用辅助文件进行索引,并且对准随机访问的显式默认支持将是有帮助的(即使它是大粒度的 - 就像能够以每10 MB的间隔开始读取一样)。是否有另一种压缩格式比gzip更好地支持随机读取?

编辑:正如我所提到的,我希望在压缩数据中进行二进制搜索。我不需要寻找特定的(未压缩的)位置 - 只是在压缩文件中寻找一些粗粒度。我只是希望支持诸如“将压缩文件中的数据大约50%(25%,12.5%等)开始解压缩。”

13 个答案:

答案 0 :(得分:31)

看看 dictzip 。它与gzip兼容,允许粗随机访问。

摘自其手册页:

  

dictzip 使用 gzip (1)算法(LZ77)以某种方式压缩文件   与gzip文件格式完全兼容。 gzip的扩展   文件格式(Extra Field,在RFC 1952的2.3.1.1中描述)允许额外的数据   存储在压缩文件的标题中。像gzip和zcat这样的程序   将忽略这些额外的数据。但是,[dictzcat --start]会使用   此数据对文件执行伪随机访问。

我在Ubuntu中有dictzip包。或者其源代码位于dictd-*.tar.gz。它的许可证是GPL。你可以自由学习。

更新

我改进了dictzip,没有文件大小限制。 My implementation已获得麻省理工学院的许可。

答案 1 :(得分:18)

我不知道任何支持随机访问未压缩数据中特定位置的压缩文件格式(除多媒体格式外),但您可以自己酿造。

例如,bzip2压缩文件由大小<1MB未压缩的独立压缩块组成,它们由魔术字节序列分隔,因此您可以解析bzip2文件,获取块边界,然后只解压缩右块。这需要一些索引来记住块的起始位置。

尽管如此,我认为最好的解决方案是将您的文件拆分为您选择的块,然后使用zip或rar等一些归档程序压缩它,这些归档程序支持随机访问归档中的各个文件。

答案 2 :(得分:9)

.xz file format(使用LZMA压缩)似乎支持这一点:

  

随机访问读取:数据可以拆分为独立的压缩块。每个.xz文件都包含一个块的索引,当块大小足够小时,可以进行有限的随机访问读取。

这应该足以满足您的目的。缺点是liblzma的API(用于与这些容器进行交互)似乎没有详细记录,因此可能需要花费一些精力来确定如何随机访问块。

答案 3 :(得分:7)

存在用于提供对gzip和bzip2档案的随机访问的解决方案:

I'm looking for something for 7zip

答案 4 :(得分:4)

bgzip可以压缩gzip变体中的文件,该变体是可索引的(并且可以由gzip解压缩)。这在一些生物信息学应用程序中与tabix索引器一起使用。

请参阅此处的说明:http://blastedbio.blogspot.fr/2011/11/bgzf-blocked-bigger-better-gzip.html,此处:http://www.htslib.org/doc/tabix.html

我不知道它在多大程度上适用于其他应用程序。

答案 5 :(得分:3)

我不确定这在您的确切情况下是否实用,但您不能将每个大文件压缩成较小的文件,比如10 MB吗?您最终会得到一堆文件:file0.gz,file1.gz,file2.gz等。根据原始大小中的给定偏移量,您可以搜索名为"file" + (offset / 10485760) + ".gz"的文件。未压缩存档中的偏移量为offset % 10485760

答案 6 :(得分:3)

因为无损压缩在某些区域比其他区域效果更好, 如果将压缩数据存储到方便长度BLOCKSIZE的块中,即使每个块具有完全相同数量的压缩字节,一些压缩块也将扩展为比其他块更长的明文块。

你可能会看 “压缩:下一代文本检索系统的关键” 作者:Nivio Ziviani,Edleno Silva de Moura,Gonzalo Navarro和Ricardo Baeza-Yates 在 计算机杂志2000年11月 http://doi.ieeecomputersociety.org/10.1109/2.881693

他们的解压缩器占用1,2或3个整个字节的压缩数据,并将(使用词汇表)解压缩成一个完整的单词。 可以直接在压缩文本中搜索单词或短语, 结果比搜索未压缩的文本更快。

它们的解压缩程序允许您使用普通(字节)指针指向文本中的任何单词,并立即从该点开始解压缩。

您可以为每个单词提供唯一的2字节代码,因为您的文本中可能只有少于65,000个唯一单词。 (KJV圣经中有近13,000个独特单词)。 即使有超过65,000个单词,将前256个双字节代码“单词”分配给所有可能的字节也非常简单,因此您可以拼出不在65,000左右的词典中的单词“最常见”单词和短语”。 (通过将频繁的单词和短语打包成两个字节而获得的压缩 通常值得“扩展”偶尔拼写出一个单词,每个字母使用两个字节)。 有多种方法可以选择能够提供足够压缩的“频繁单词和短语”词典。 例如,您可以调整LZW压缩器以将其多次使用的“短语”转储到词典文件,每个短语一行,并在所有数据上运行它。 或者你可以在词典文件中任意将你的未压缩数据切换成5个字节的短语,每个短语一行。 或者,您可以将未压缩的数据切换为实际的英语单词,并将每个单词(包括单词开头的空格)放入词典文件中。 然后使用“sort --unique”来消除该词典文件中的重复单词。 (选择完美的“最佳”词典词表仍然被认为是NP难?)

将词典存储在巨大的压缩文件的开头,将其填充到一些方便的BLOCKSIZE,然后存储压缩文本 - 一系列两个字节的“单词” - 从那里到文件的末尾。 据推测,搜索者会在解压缩过程中读取一次该词典并将其保存在RAM中的某种快速解码格式,以加速将“双字节代码”解压缩为“可变长度短语”。 我的第一个草稿将从每个短语列表中简单的一行开始,但您可能稍后转而使用某种增量编码或zlib以更压缩的形式存储词典。

您可以在压缩文本中选择任意随机字节偏移量,然后从那里开始解压缩。 我认为不可能制作更精细的随机访问压缩文件格式。

答案 7 :(得分:3)

两种可能的解决方案:

  1. 让操作系统处理压缩,创建和挂载包含所有文本文件的压缩文件系统(SquashFS,clicfs,cloop,cramfs,e2compr或其他),并且不要在应用程序中执行任何有关压缩的操作

  2. 直接在每个文本文件上使用clicfs(每个文本文件一个clicfs),而不是压缩文件系统映像。可以将“mkclicfs mytextfile mycompressedfile”视为“gzip&lt; mytextfile&gt; mycompressedfile”和“clicfs mycompressedfile目录”,作为通过文件“directory / mytextfile”随机访问数据的方式。

答案 8 :(得分:1)

我不知道它是否已被提及,但Kiwix项目在这方面做了很多工作。通过他们的程序Kiwix,他们提供随机访问ZIM文件档案。压缩也很好。该项目源于对维基百科的离线副本的需求(已经以非压缩形式达到100 GB以上,包括所有媒体)。他们成功地获取了25 GB的文件(没有大多数媒体的维基百科的单文件实施例)并将其压缩为一个可怜的8 GB zim文件存档。通过Kiwix计划,您可以使用所有相关数据调用维基百科的任何页面,比网上冲浪更快。

尽管Kiwix程序是基于维基百科数据库结构的技术,但它证明您可以同时具有出色的压缩率和随机访问。

答案 9 :(得分:1)

这是一个非常古老的问题,但看起来zindex可以提供一个很好的解决方案(虽然我没有多少经验)

答案 10 :(得分:1)

如先前在zlib's zran.c source code上所展示的,只要已创建索引,就可以随机访问gzip格式。

我已经在zlib的 zran.c 上开发了一个命令行工具,该工具可为gzip文件创建索引:https://github.com/circulosmeos/gztool

它甚至可以为仍在增长的gzip文件创建索引(例如,由rsyslog直接以gzip格式创建的日志),从而在实践中将索引创建时间减少为零。请参见-S监督)选项。

答案 11 :(得分:0)

razip支持随机访问,性能优于gzip / bzip2,必须针对此支持进行调整 - 以“ok”随机访问为代价减少压缩:

http://sourceforge.net/projects/razip/

答案 12 :(得分:0)

我是压缩特定类型生物数据的开源工具的作者。这个名为starch的工具按染色体分割数据,并使用这些分区作为索引,以便快速访问较大档案中的压缩数据单元。

转换每个染色体数据以去除基因组坐标中的冗余,并使用bzip2gzip算法压缩转换后的数据。偏移量,元数据和压缩基因组数据连接成一个文件。

我们的GitHub网站提供了源代码。我们已经在Linux和Mac OS X下编译了它。

对于您的情况,您可以在标头中存储(10 MB或其他)偏移到自定义存档格式。您可以解析标题,检索偏移量,并通过fseek + current_offset_sum逐步header_size整个文件。