Compression 如何击败gzip(或其他无损压缩)

Compression 如何击败gzip(或其他无损压缩),compression,gzip,Compression,Gzip,根据鸽子洞原理,每个无损压缩算法都可能被“击败”,即对于某些输入,它产生的输出比输入长。是否有可能显式构造一个文件,当该文件馈送到gzip或其他无损压缩程序时,将导致(更)大的输出?(或者,更好的是,一个文件在随后的压缩过程中无限膨胀?尝试gzip以下命令生成的文件: echo a > file.txt 2字节文件的压缩是31字节gzip文件的结果 一个包含1个字节的文本文件(例如一个类似“A”的字符)存储在磁盘上的1个字节中,但winrar将其压缩为94个字节,压缩为141个字节 我知

根据鸽子洞原理,每个无损压缩算法都可能被“击败”,即对于某些输入,它产生的输出比输入长。是否有可能显式构造一个文件,当该文件馈送到gzip或其他无损压缩程序时,将导致(更)大的输出?(或者,更好的是,一个文件在随后的压缩过程中无限膨胀?

尝试gzip以下命令生成的文件:

echo a > file.txt

2字节文件的压缩是31字节gzip文件的结果

一个包含1个字节的文本文件(例如一个类似“A”的字符)存储在磁盘上的1个字节中,但winrar将其压缩为94个字节,压缩为141个字节

我知道这是一种欺骗的回答,但它是有效的。我认为这将是您将看到的原始尺寸和“压缩”尺寸之间最大的%差异


看看压缩的公式,它们相当简单,要使“压缩”文件比原始文件大,最基本的方法是避免任何重复数据。

随机数据,或使用良好加密的数据可能是最好的

但是,任何一个好的打包程序,一旦决定不能压缩数据,就应该只增加固定的开销。(@Frank)。对于固定开销,一个空文件或一个字符的开销百分比最大


对于包含文件名(例如rar、zip、tar)的打包程序,您当然可以将文件名设置为真正的长:-)

好吧,我假设它最终会最大化,因为位模式会重复,但我只是做了:

touch file
gzip file -c > file.1
...
gzip file.9 -c > file.10
得到:

  0 bytes: file
 25 bytes: file.1
 45 bytes: file.2
 73 bytes: file.3
103 bytes: file.4
122 bytes: file.5
152 bytes: file.6
175 bytes: file.7
205 bytes: file.8
232 bytes: file.9
262 bytes: file.10
以下是24380个图形文件(事实上,这让我非常惊讶):

我并不期望这种增长,我只期望线性增长,因为它应该只是用模式字典将现有数据封装在一个标题中。我本打算运行1000000个文件,但在此之前,我的系统磁盘空间已经用完了

如果要复制,以下是生成文件的bash脚本:

#!/bin/bash

touch file.0

for ((i=0; i < 20000; i++)); do
    gzip file.$i -c > file.$(($i+1))
done

wc -c file.* | awk '{print $2 "\t" $1}' | sed 's/file.//' | sort -n > filesizes.txt
#/bin/bash
触摸文件
对于((i=0;i<20000;i++));做
gzip文件。$i-c>文件。$($i+1))
完成
wc-c文件。*| awk'{print$2”\t“$1}'| sed's/file.//'| sort-n>filesizes.txt

生成的filesizes.txt是一个以制表符分隔的排序文件,用于您最喜欢的绘图工具。(您必须手动删除“总计”字段,或将其脚本化。)

所有这些压缩算法都在寻找冗余数据。如果文件中没有冗余或冗余很少(比如一系列的
abac…az
bcbd…bz
cdce…cz
,等等),那么“压缩”的输出很可能是一种膨胀。

我希望大多数压缩算法足够聪明,即使它们会让事情变得更糟,也不会压缩。他们可能会在头文件中添加固定数量的字节,但如果只存储原始字节,则生成一个大50%的文件将是一个相当严重的错误。你的无损压缩方案必须是可击败的“证据”有一个小缺陷:实际上n只鸟有n个洞。因此,将任何输入压缩0%且不添加任何头的“压缩”方案将不会失败:-)“当将文件馈送到gzip或其他无损压缩程序时,将导致(更)大的输出?”嗯,您可以在Linux上执行
cat/dev/uradom | gzip>~/1.bin
。。即使压缩只会增加恒定的开销,如果一个文件在每一个级别上都不压缩,那么它能以这种方式无限增长吗?(我知道这纯粹是理论上的:)不。随机数据,因为它是随机的,将包括一些压缩非常非常好的序列。@DJClayworth,但随机数据没有压缩所需的结构,因此,压缩器将丢失对不好序列的位的编码。@neworder yes每一级压缩几乎肯定会添加一个头,压缩的数据将无法再压缩。避免递归开销的唯一方法是声明“foo”压缩器检测到它正试图压缩“foo”文件,只返回原件。类似地,解压缩程序必须在不修改的情况下传递非foo文件。而且误报会有很多问题。有趣的是,文件大小似乎没有按特定顺序增加,或者没有特定的关系。它看起来像是从标题/字典等中纯线性增加。@Douglas:这也是我的期望,但我更新了更多的文件。显然,外观可能是骗人的。请注意,gzip是一种文件格式,而不仅仅是像deflate这样的压缩数据格式;它只是使用deflate。