如何连接两个或多个 gzip 文件/流
Posted
技术标签:
【中文标题】如何连接两个或多个 gzip 文件/流【英文标题】:How to concat two or more gzip files/streams 【发布时间】:2010-11-11 17:04:45 【问题描述】:我想连接两个或多个 gzip 流而不重新压缩它们。
我的意思是我将 A 压缩为 A.gz,将 B 压缩为 B.gz,我想使用 C 或 C++ 将它们压缩为单个 gzip (A+B).gz 而无需再次压缩。
几个注意事项:
即使您可以连接两个文件,而 gunzip 知道如何处理它们,大多数程序也无法处理两个块。 我曾经见过一个代码示例,该示例仅通过解压缩文件然后操作原始文件来执行此操作,这比正常重新压缩要快得多,但仍需要 O(n) CPU 操作。 不幸的是,我找不到这个我曾经找到过的示例(仅使用解压缩进行连接),如果有人能指出它,我会很感激。注意:它不是 this 的重复,因为建议的解决方案不符合我的需要。
澄清编辑:
我想连接几个压缩的 html pices 并将它们作为一个页面发送到浏览器,根据请求:“Accept-Encoding: gzip”,响应为“Content-Encoding: gzip”
如果像cat a.gz b.gz >ab.gz
那样简单地连接流,Gecko (firefox) 和 KHTML 网络引擎只会得到第一部分 (a); IE6 不显示任何内容,Google Chrome 将第一部分 (a) 正确显示,将第二部分 (b) 显示为垃圾(根本不解压缩)。
只有 Opera 能很好地处理这个问题。
所以我需要创建一个包含多个块的单个 gzip 流,并在不重新压缩的情况下发送它们。
更新: 我在 zlib 的示例中找到了 gzjoin.c,它只使用解压缩来完成。问题是解压还是比较慢他们简单memcpy
.
它仍然比最快的 gzip 压缩快 4 倍。但这还不够。
我需要的是找到我需要与 gzip 文件一起保存的数据,以便 没有运行解压程序,如何在压缩过程中找到这些数据。
【问题讨论】:
您真的要压缩它们还是只是将它们连接到同一个文件中? 我想创建一个由另外两个 gzip 压缩文件/流/内存块组成的 gzip 压缩文件/流/内存块,而无需解压缩、连接它们并再次压缩它们。 在编辑中查看说明。 gzjoin.c 需要解压第二个流以与流保持同步。由于 zlib 流不包含索引,因此这是必需的。理论上你可以提前gzip压缩的时候加上索引,修改gzjoin来使用这个索引。但这不适合胆小的人...... 如果你把这个写成答案,我可以接受。 【参考方案1】:看看RFC1951和RFC1952
格式只是一组成员,每个成员由三个部分组成,一个标题、数据和一个尾部。数据部分本身就是一组块,每个块都有一个标头和数据部分。
要模拟 gzip 压缩两个(或多个文件)串联结果的效果,您只需正确调整标头(例如最后一个块标志)和尾部并复制数据部分。
有一个问题,预告片有一个未压缩数据的 CRC32,我不确定当你知道零件的 CRC 时这个是否容易计算。
编辑:您发现的 gzjoin.c 文件中的 cmets 表明,虽然可以在不解压缩数据的情况下计算 CRC32,但还有其他需要解压缩的东西。
【讨论】:
如果您有片段的 CRC,您可以使用它们来计算最终的 CRC。如果我没记错的话,如果你有带有 Crc1 的 Msg1 和带有 Crc2 的 Msg2,那么要计算 [Msg1,Msg2] 的 crc,你可以改为计算 [Crc1, 0,0,0,0 ...(零 Msg2 长度)的 crc次)] 并与 Crc2 异或。可能在某个地方需要一个人的补充,但想法是这样的。【参考方案2】:gzip 手册说两个 gzip 文件可以按照您的尝试连接。
http://www.gnu.org/software/gzip/manual/gzip.html#Advanced-usage
看来其他工具可能已损坏。如本错误报告中所示。 http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=97263
除了向每个浏览器制造商提交错误报告并希望他们遵守之外,也许您的程序可以缓存所需数据的最常见连接。
正如其他人所提到的,您也许可以进行手术: http://www.gzip.org/zlib/rfc-gzip.html
这需要最终未压缩文件的 CRC-32。通过添加各个子文件的长度,可以很容易地计算出未压缩文件所需的大小。
在最后一个链接的底部,有用于计算名为 update_crc 的运行 crc-32 的代码。
每次运行进程时计算未压缩文件的 crc,可能比 gzip 算法本身便宜。
【讨论】:
说到.NET库,我亲身验证过这个库支持多部分GZip文件:icsharpcode.net/opensource/sharpziplib【参考方案3】:看来单个文件的原始压缩是由您完成的。看起来所需的结果(几部分的连接)足够小,可以在一页中发送到 Web 浏览器。 在这种情况下,您的效率问题似乎没有根据。
请注意,(1) gzjoin.c 方法很可能是您可以解决问题的最佳答案,如所述 (2) 它是由 gzip 发起者之一执行的复杂显微外科手术,可能不是接受广泛的压力测试。
请考虑一种无聊且可理解的可靠方法:存储未压缩的原始片段,然后选择所需片段,并连接并压缩它们。请注意,压缩比可能比将小压缩块粘合在一起获得的压缩比更好。
【讨论】:
是的,我是这两个块的发起者,所以我什至可以用它们保存一些元数据,或者做一些假设。所以我知道 gzjoin 最简单且不易出错,但它仍然比简单的“gzip -1”快 4 倍。我需要 memcpy 接近加速。这个想法:我缓存了一些准备好的块并根据用户请求将它们组合起来。 您还没有解释为什么您需要“memcpy near speedup”处理看似少量的数据。也许您可以告诉我们您每秒需要提供多少这些页面以及它们有多大。 假设页面和块很大,负载非常高。【参考方案4】:如果tar
他们不是不可能的(因为链接的cat
solution 对您不可行):
tar cf A_B.gz.tar A.gz B.gz
然后,让他们回来:
tar xf A_B.gz.tar
【讨论】:
不,我说的不是焦油 我明白你现在在说什么了。 . .您想要执行相当于“gunzip A.gz & guzip B.gz & cat A B > C & gzip C.gz A B”的操作,但不进行解压缩,以期实现 O(1) 处理时间。 gzip 是不会这样做的,我不知道是否有一个实用程序可以。但即使有,它仍然需要 O(n) 时间,因为它必须(至少)检查压缩文件以找出如何压缩它们。 将它们 tar 有什么问题,它可以实现您想要做的一切。 显然他的代码无法处理两个 gzip 文件。他想把这两个文件放在一起,得到一个 gzip 文件,而不是解压这两个原始文件。 “将它们 tar 有什么问题”——如果这与我正在尝试做的事情类似,则需要压缩数据。以上是关于如何连接两个或多个 gzip 文件/流的主要内容,如果未能解决你的问题,请参考以下文章