【问题标题】:How to do compression that allows random read access to the compressed data?如何进行压缩以允许对压缩数据进行随机读取访问?
【发布时间】:2015-05-05 00:50:15
【问题描述】:

我正在将实时数据的小型可变大小帧(每个帧从 15 到 4k 字节)写入文件。数据总大小可以达到几十G,所以我想压缩一下。

但是从文件中读取时,我希望能够在数据内部寻找而不必解压缩所有内容(直到感兴趣的点)。如果有一种方法可以在入口点处开始解压缩,那将会很棒,例如1MB 的间隔,我可以跳转到并读取压缩数据中下一帧的时间戳,然后开始解压缩,而无需从开始到那时解压缩所有内容。

但我不想为此实现整个压缩算法。如果生成的文件也与 gzip 等广泛使用的格式兼容,那就太好了,但易于实现(并且不会过多降低压缩率)更为重要。

当试图保持与 gzip 的兼容性时,可以通过使用多个 gzip members,每个大约 1MB 大小,并将下一个时间戳信息放入(每个成员)extra field 来完成。如果我没记错的话,缺点是字典信息在每个成员的开头都被丢弃了。 (虽然我不知道是复制字典还是为每个成员重新开始消耗更少的字节/cpu 周期。)

有多种解决方案可以解决“随机读取访问”问题inJavaotherlanguages,但我找不到在 CLR 上运行的解决方案。

另一个要求是必须以流式方式执行压缩,即压缩完成后我不能在最后写入索引。因此需要预先定义入口点,或者将到达入口点的信息与压缩数据交织在一起,这样即使进程被杀死或崩溃,我也可以使用已经写入磁盘的内容。

.net 的 GZipStreamSharpZipLib 都没有提供开箱即用的钩子来提供帮助。

想法?

【问题讨论】:

  • 考虑到帧的大小,我认为最好只对文件夹使用文件系统压缩。
  • @leppie 框架的大小应该与解决方案无关。相关的是入口点的间隔,我暂定为1MB。但更重要的是,结果应该是一个压缩文件,即我可以复制到其他机器、通过电子邮件发送等并保留压缩的东西。

标签: .net compression zip gzip random-access


【解决方案1】:

您已经找到了很多好的方法。一系列 gzip 成员是一个非常好的解决方案,其中每个成员都有一个额外的字段,该字段具有该成员的长度,以便您可以跳过成员。有一些小的压缩损失,但如果您希望能够在没有先前解压缩数据的情况下在流中的指定点开始解压缩,这是无法避免的。您可以通过增大成员来减少这种影响。

【讨论】:

  • 这也意味着我必须缓冲完整的(压缩的)成员,以便我知道将其写入额外字段的大小。对于.net,这也意味着扩展一个现有的库,以便我可以编写和读取额外的字段,这是我最终可能采取的路线。
  • 是的。但你说的是小成员。您真的如此受限以至于无法为压缩数据提供几 MB 的缓冲区吗?
【解决方案2】:

为了实现GZipStream缺乏的自定义GZIP功能(它甚至没有解压缩多个gzip成员,当我尝试时,虽然gunzip可以),实际上没有必要重新实现压缩算法。 GZipStream 使用 DeflateStream 并且只添加了标头和 CRC,所以我只需要实现我自己的 GZipStream,使用 DeflateStream 为我做压缩,这看起来很简单。 p>

感谢 Mark Adler 确认了我对 gzip 规范的推测。因此,解决方案既简单明了,又与 gzip 规范兼容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-03
    • 2012-12-22
    • 2016-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多