什么是允许在文件中随机读/写的最佳压缩算法?

时间:2008-10-25 13:38:38

标签: compression random-access huffman-code adaptive-compression

允许文件中随机读/写的最佳压缩算法是什么?

我知道任何自适应压缩算法都是不可能的。

我知道霍夫曼编码是不可能的。

有没有人有更好的压缩算法允许随机读/写?

我认为你可以使用任何压缩算法,如果你用块写它,但理想情况下我不想一次解压缩整个块。但是,如果您有关于简单方法的建议以及如何知道块边界,请告诉我。如果这是您的解决方案的一部分,请告诉我您想要阅读的数据跨越块边界时的操作?

在您的答案的上下文中,请假设有问题的文件是100GB,有时我想读取前10个字节,有时我想读取最后19个字节,有时我想要在中间读取17个字节。

7 个答案:

答案 0 :(得分:20)

我对那些暗示这样的事情是不可能的回应感到震惊。

让这些人从未听说过“压缩文件系统”, 自从1993年Stac Electronics因压缩文件系统技术被微软起诉以来,它一直存在?

我听说LZSLZJB是实现压缩文件系统的流行算法,这些算法必然需要随机访问读取和随机访问写入。

也许最简单和最好的事情是打开该文件的文件系统压缩,让操作系统处理细节。 但如果您坚持手动处理,也许您可​​以通过阅读NTFS transparent file compression来获取一些提示。

同时退房: "StackOverflow: Compression formats with good support for random access within archives?"

答案 1 :(得分:4)

razip格式支持随机访问读取,其性能优于gzip / bzip2,必须针对此支持进行调整:

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

答案 2 :(得分:3)

基于字典的压缩方案,每个字典条目的代码使用相同的大小进行编码,这将导致能够以任何倍数的代码大小开始读取,并且如果代码没有用,则写入和更新很容易他们的背景/邻居。

如果编码包含区分代码开头或结尾的方法,那么您不需要代码长度相同,并且您可以开始在文件中间的任何位置读取。如果您从流中的未知位置读取,此技术会更有用。

答案 3 :(得分:3)

我认为Stephen Denne可能会在这里做点什么。想象:

  • 将序列压缩成代码
  • 字典映射代码 - >序列
  • 文件就像一个文件系统
    • 每次写入都会生成一个新的“文件”(一个字节序列,根据字典压缩)
    • “filesystem”跟踪哪个“文件”属于哪个字节(开始,结束)
    • 根据字典
    • 压缩每个“文件”
    • 根据“filesystem”
    • 以文件方式读取工作,解压缩并检索字节
    • 写道“使文件”无效,附加新的“文件”以替换无效的文件
  • 此系统需要:
    • 文件系统的碎片整理机制
    • 不时压缩字典(删除未使用的代码)
  • 做得不错,可以在没人看(空闲时间)或创建新文件并最终“切换”时进行内务管理

一个积极的效果是字典将应用于整个文件。如果你可以节省CPU周期,你可以定期检查重叠“文件”边界的序列,然后重新组合它们。

这个想法适用于真正的随机读取。如果你只是要阅读固定大小的记录,这个想法的某些部分可能会变得更容易。

答案 4 :(得分:1)

我不知道任何允许随机读取的压缩算法,更不用说随机写入。如果您需要这种能力,最好的办法是将文件压缩成块而不是整体。

例如。我们首先看一下只读案例。假设您将文件分解为8K块。您压缩每个块并按顺序存储每个压缩块。您需要记录每个压缩块的存储位置和大小。然后,假设您需要从偏移量O开始读取N个字节。您需要找出它所在的块(O / 8K),解压缩该块并获取这些字节。您需要的数据可能跨越多个块,因此您必须处理该场景。

当您希望能够写入压缩文件时,事情会变得复杂。你必须处理压缩块越来越大。您可能需要为每个块添加一些额外的填充,以防它扩展(它仍然是未压缩的相同大小,但不同的数据将压缩到不同的大小)。如果压缩数据太大而无法放回原来的空间,您甚至可能需要移动块。

这基本上是压缩文件系统的工作原理。您可能最好为文件打开文件系统压缩,然后正常读/写它们。

答案 5 :(得分:1)

压缩就是要从数据中删除冗余。不幸的是,冗余不太可能在整个文件中以单调的均匀度进行分配,而这是唯一可以预期压缩细粒度随机访问的情况。

但是,您可以通过维护在压缩期间构建的外部列表来关闭以进行随机访问,该列表显示未压缩数据流中所选点与压缩数据流中位置之间的对应关系。您显然必须选择一种方法,其中源流与其压缩版本之间的转换方案不会随着流中的位置而变化(即没有LZ77或LZ78;相反,您可能想要使用Huffman或byte-对编码。)显然这会产生很多开销,你必须决定你想要在“书签点”所需的存储空间和解压缩流所需的处理器时间之间进行权衡。书签指向获取您正在寻找的数据。

至于随机访问写作......这几乎是不可能的。如前所述,压缩是关于从数据中删除冗余。如果您尝试替换可能被压缩的数据,因为它对于没有具有相同冗余的数据是多余的,那么它根本不适合。

但是,根据你要做多少随机访问写入 - 您可以通过维护一个稀疏矩阵来表示它,该矩阵表示压缩后写入文件的所有数据。在所有读取中,您将检查矩阵以查看您是否正在读取压缩后写入的区域。如果没有,那么你将转到数据的压缩文件。

答案 6 :(得分:-2)

由于两个相关原因,没有压缩方案可以允许细粒度的随机访问:

  • 您无法准确知道所需数据的压缩文件到底有多远,因此
  • 无法知道符号的起始位置(在霍夫曼的位置,对于算术编码更糟糕)。

我只能建议将文件视为广播流并插入频繁的同步/位置标记,但显而易见的开销(同步标记不仅会占用空间,而且会使编码复杂化,因为它必须避免“意外”同步标记!)。或者,为了避免寻找像二进制搜索这样的东西(通过优化,你可以更好地猜测从哪里开始比中间),你可以在文件的开头或结尾包含一个“目录”。 / p>

至于随机访问写作......我想不出任何整洁的解决方案:(