方法1:不压缩它们
结果:
Resulting Size: 62 MB
Percent of initial size: 100%
方法2:压缩每个文件并压缩向他发送10,000个xml文件
命令:
for x in $(ls -1) ; do echo $x ; zip "$x.zip" $x ; done
结果:
Resulting Size: 13 MB
Percent of initial size: 20%
>方法3:创建一个包含10,000个xml文件的单个zip
命令:
zip all.zip $(ls -1)
结果:
Resulting Size: 12 MB
Percent of initial size: 19%
方法4:将文件连接成一个文件并压缩
命令:
cat *.xml > oneFile.txt ; zip oneFile.zip oneFile.txt
结果:
Resulting Size: 2 MB
Percent of initial size: 3%
问题:
为什么当我拉一个拉链时我会得到更好的效果文件?
我希望使用方法3可以获得比方法2更好的结果,但事实并非如此。为什么?
此行为是特定于
zip
的吗?如果我尝试使用gzip
,会得到不同的结果吗?其他信息:
$ zip --version
Copyright (c) 1990-2008 Info-ZIP - Type 'zip "-L"' for software license.
This is Zip 3.0 (July 5th 2008), by Info-ZIP.
Currently maintained by E. Gordon. Please send bug reports to
the authors using the web page at www.info-zip.org; see README for details.
Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip,
as of above date; see http://www.info-zip.org/ for other sites.
Compiled with gcc 4.4.4 20100525 (Red Hat 4.4.4-5) for Unix (Linux ELF) on Nov 11 2010.
Zip special compilation options:
USE_EF_UT_TIME (store Universal Time)
SYMLINK_SUPPORT (symbolic links supported)
LARGE_FILE_SUPPORT (can read and write large files on file system)
ZIP64_SUPPORT (use Zip64 to store large files in archives)
UNICODE_SUPPORT (store and read UTF-8 Unicode paths)
STORE_UNIX_UIDs_GIDs (store UID/GID sizes/values using new extra field)
UIDGID_NOT_16BIT (old Unix 16-bit UID/GID extra field not used)
[encryption, version 2.91 of 05 Jan 2007] (modified for Zip 3)
编辑:元data
一个答案表明,区别是存储在zip中的系统元数据。我认为情况并非如此。为了进行测试,我执行了以下操作:
for x in $(seq 10000) ; do touch $x ; done
zip allZip $(ls -1)
生成的zip文件为1.4MB。这意味着仍有大约10 MB的无法解释的空间。
#1 楼
压缩时,Zip分别处理每个文件的内容。每个文件将具有其自己的压缩流。压缩算法(通常为DEFLATE)内支持识别重复部分。但是,Zip中不支持在文件之间查找冗余。这就是为什么当内容位于多个文件中时会有这么多额外空间的原因:它将相同的压缩流多次放入文件中。
评论
这也是为什么某些压缩工具使您可以选择单独压缩文件还是将其压缩为单个实体。 (尽管通常来说,这也意味着您必须解压缩更多的存档,而不是仅查看其中的单个文件。)
– JAB
15年12月14日在19:35
@JAB:诸如7z和rar的压缩工具使用术语“实体”存档将多个文件从头到尾打包到更大的压缩流中。使用像64MiB这样的中等大小的块,对单个文件的随机访问可能需要从其所在的压缩块开始对多达64MiB的数据进行解压缩。您可以在随机访问和查找跨文件冗余之间取得不错的平衡。 7z可以使用更有效(但压缩速度较慢)的LZMA压缩方案,这是与zip相比的另一个优点。
– Peter Cordes
2015年12月15日4:29
您是说Zip文件规范中不支持Zip查找文件之间的冗余吗?
–sixtyfootersdude
2015年12月16日15:12
@sixtyfootersdude许多压缩算法(例如DEFLATE)作为流运行。为了恢复足够的信息以解压缩一部分流,您需要处理整个流直到那时。如果他们试图找到文件之间的冗余,则必须解压缩所有1000个文件才能到达最后一个文件。实际上,这通常是tgz的工作方式。但是,zip旨在让您提取单个文件。 tgz被设计成全有或全无
–Cort Ammon
15年12月16日在21:46
@sixtyfootersdude-是的。解释一下Cort:pkzip规范不支持跨文件工作。如果他们这样做,则提取一个文件可能需要提取整个存档(以及每个文件)。
–詹姆斯·斯内尔(James Snell)
15年12月18日在11:40
#2 楼
ZIP压缩基于要压缩的数据中的重复模式,文件越长,压缩效果越好,因为可以找到并使用越来越多的模式。如果您压缩一个,则简化。在文件中,每个结果zip文件中都必须包含将(短)代码映射到(较长)模式的字典。如果您压缩一个长文件,则字典将被“重用”,并且在所有内容上都变得更加有效。
如果您的文件甚至有点相似(就像文本一样),请重新使用“字典”变得非常有效,结果总拉链要小得多。
评论
ZIP同时存档和压缩。这是否意味着ZIP会分别压缩每个文件,即使它们最终都位于同一个ZIP文件中?
– Gerrit
2015年12月14日20:00
这类操作必须-想象您删除了一个文件,您不希望它花费另一个半小时用一个新的“字典”重新压缩其余文件。 -同样,它可能假设不同的文件需要非常不同的“字典”。
– Aganju
2015年12月14日20:02
我不明白为什么要这么做。使用Unix工具,我将首先使用tar归档文件,然后使用gzip / bz2 / lzma对其进行压缩。压缩算法并不关心存档中编码了多少文件。此外,从压缩档案中删除单个文件的确有多普遍?我认为我从未做到过。
– Gerrit
2015年12月14日20:07
我不同意,这可能是一个好方法。我没有设计或编写ZIP。我只是说了怎么办...
– Aganju
15年12月14日在20:10
@gerrit它有其自身的问题。 Zip旨在允许您快速访问存档中的任何文件-尝试从100 GiB UHA存档中解压缩单个文件,您将了解为什么他们选择这种方式。它还设计用于附加-您可以拥有备份zip,并仅根据需要不断添加(或替换)文件。使用存档时,所有这些都是巨大的帮助。折衷方案是,如果要压缩非常相似的文件(不是很常见),则无法利用相似性来减小归档文件的大小。
–罗安
2015年12月15日在8:55
#3 楼
在Zip中,每个文件分别压缩。相反的是“固体压缩”,即文件被压缩在一起。默认情况下,7-zip和Rar使用实体压缩。 Gzip和Bzip2无法压缩多个文件,因此首先使用Tar,其效果与实体压缩相同。由于xml文件具有相似的结构,并且如果将文件一起压缩,则内容可能相似。
例如,如果文件包含字符串
"<content><element name="
,并且压缩程序已经在另一个文件中找到该字符串,则如果压缩程序未找到该字符串,它将用一个指向先前匹配项的小指针替换它使用“固体压缩”,文件中字符串的第一次出现将记录为较大的文字。#4 楼
Zip不仅存储文件的内容,还存储文件元数据,例如拥有的用户ID,权限,创建和修改时间等。如果您有一个文件,则有一组元数据;如果您有10,000个文件,则有10,000套元数据。评论
很好,但是系统元数据仅占用1.4MB的空间。看到我的编辑。
–sixtyfootersdude
15年12月14日在18:02
我对zip算法不熟悉,但是元数据不仅是文件信息,还包括大小和字典之类的东西,可能还包括一些有关字符分布的信息。非空文本文件上的字典将为非零。这可能就是为什么您看到xml文件中的元数据大于空文件的原因。
–本·理查兹(Ben Richards)
15年12月14日在18:54
这是我的第一个想法。压缩文件标题信息
–WernerCD
15年12月14日在19:40
这仅说明2和3之间的差异-而不是4。
–罗安
2015年12月15日上午8:56
@Luaan不,在2和3中,所有10,000个文件的元数据都包含在一个或多个zip文件中,因此文件总大小几乎相同。在4中,只有一个文件的元数据,而zip文件要小得多。
–麦克·斯科特(Mike Scott)
2015年12月15日在12:01
#5 楼
OP遗漏的一个选项是将所有文件压缩在一起,同时关闭压缩功能,然后将压缩结果设置为最大的压缩结果文件压缩。通过允许压缩利用跨文件边界的冗余来粗略地模拟* nix .tar.Z,.tar.gz,.tar.bz等压缩档案的行为(ZIP算法在单个运行时无法执行)通过)。这样可以在以后提取单个XML文件,但可以最大程度地提高压缩率。缺点是提取过程需要额外的步骤,暂时占用了比普通.zip所需磁盘空间更多的磁盘空间。随处可见免费工具,例如7-Zip来扩展tar。对于Windows系列,实际上没有理由不使用.tar.gz或.tar.bz等,因为Linux,OS X和BSD都具有用于操作它们的本机工具。
评论
gzip和bzip2可能会变得更糟,因为它们在设计时就考虑了压缩流,因此它们将不得不开始输出压缩数据,甚至所有压缩数据都不得而知。
–rackandboneman
15年12月16日在12:31
@rackandboneman:这是压缩文件时要做出的权衡,该文件大于压缩时愿意使用的内存量。 (而且,找到全局最优值所需的CPU时间也将是巨大的。)巨大的压缩字典还可以增加解压缩所需的内存。这是LZMA(xz / 7-zip)的选项。无论如何,自适应词典一旦可见就可以选择模式。并非仅基于前32k构建静态编码系统。这就是为什么gzip不烂的原因。
– Peter Cordes
2015年12月21日在11:13
如果您需要使用zip格式,我真的很喜欢这个“技巧”。我不同意您的“没有理由不使用7-zip”的意见-如果我要将文件发送给非技术朋友,我想确保他们能够轻松打开它。如果我要发送给业务客户,那就更是如此。
–Wowfunhappy
19年3月14日在20:45
#6 楼
zip压缩格式分别存储和压缩每个文件。它不利用文件之间的重复,而仅利用文件中的重复。串联文件使zip可以利用所有文件之间的重复,从而大大提高了压缩率。
例如,假设每个XML文件都有一个特定的标头。该标头在每个文件中仅出现一次,但在许多其他文件中几乎相同地重复。在方法2和3中,zip无法为此压缩,但在方法4中,它可以压缩。
评论
这与5小时前已发布的前3个答案之一有何不同?
– Xen2050
2015年12月15日下午5:35
@ Xen2050差别不大,我只是认为我可以更清楚地解释它。
– BonsaiOak
2015年12月15日23:35
@BonsaiOak-然后在正确答案中添加评论,或者如果您有足够的代表,则进行编辑。如果不是,但您的评论增加了清晰度,则其他人可能会选择并编辑帖子。
– AdamV
15年12月17日在13:09
@AdamV我明白你的意思了。我的回答目前没有添加任何有用的信息,尽管可以说是我写的时候添加的。在第一个答案下已经有适当的注释,因此我也看不出添加它们的意义。您是说我应该结束我的回答吗?打开它有什么害处?
– BonsaiOak
15年12月18日在22:10
#7 楼
在Mike Scott提到的元数据旁边,压缩算法也有开销。压缩一堆单独的小文件时,您必须非常幸运能够压缩它们,以免发生这种情况。填充一个压缩块。
压缩单个整体块时,系统可以继续将数据流式传输到其算法,而无需考虑单个文件的“边界”(缺少更好的词)。
此外,众所周知ASCII具有很高的压缩系数。 plus xml经常会非常重复,使元数据成为无法像xml内容那样轻易压缩的大量数据。
最后,如果内存使用得当,zip将使用诸如字典编码之类的东西,由于其重复性,它在ascii文件上尤其有效,在XML上尤其如此。
数据压缩说明:http://mattmahoney.net/dc/dce.html
#8 楼
考虑以下XML:<root>
<element id="1" />
<element id="2" />
<other id="3" />
...
</root>
XML具有非常重复的结构,Zip利用这些重复来构建字典,该字典的模式出现次数更多,然后在压缩时,使用较少的位来存储更多的重复模式,而使用更多的位来存储较少的重复模式。
当连接这些文件时,源文件(zip的源)很大,但是包含更多的重复模式,因为XML的无聊结构的de分布在整个大文件中摊销,从而使ZIP可以使用更少的位存储这些模式。
现在,如果您将不同的XML组合到一个文件中,即使这些文件具有完全不同的标记名,压缩算法也将在所有文件上找到最佳模式分布,而不是逐个文件。
最终压缩算法已找到最佳重复模式分布。
#9 楼
除了7-Zip答案之外,还有另一种方法不太好,但是如果出于某种原因您不想使用7-Zip,则值得测试:压缩zip文件。现在,通常一个zip文件是不可压缩的,但是当它包含许多相同的文件时,压缩程序可以找到此冗余并将其压缩。请注意,在处理大量没有冗余的文件时,我也看到了很小的收获。如果您真的很在意大小,那么如果您的zip文件太多,就值得尝试。
评论
如上文所述,只有在压缩关闭的情况下进行第一个zip压缩时,这种方法才有效。
– Monty Harder
15年12月18日在21:38
@MontyHarder我已经看到它在压缩打开的情况下起作用。
–Loren Pechtel
15年12月18日在21:50
评论
如果我没记错的话,这是导致人们制作.tar.gz的现象,而不是仅仅压缩整个目录。已经问过类似的问题,tl; dr使用可靠的7zip存档。
@sixtyfootersdude作为验证某些答案的测试,您可以尝试压缩方法3中生成的拉链吗?我怀疑这会将文件大小减小到可以与方法4相当的程度。
代替$(ls -1),只需对*中的x使用*:即可; zip all.zip *
如果要使用ZIP进行整体压缩,请采取以下解决方法:首先,创建一个包含所有文件的未压缩ZIP。然后,将该ZIP放入另一个压缩的ZIP中。