假设我有 10,000 个 XML 文件。现在假设我想将它们发送给朋友。在发送之前,我想对它们进行压缩。
方法 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)
编辑:元数据
一个答案表明差异在于存储在 zip 中的系统元数据。我不认为情况如此。为了测试,我做了以下事情:
for x in $(seq 10000) ; do touch $x ; done
zip allZip $(ls -1)
生成的 zip 文件大小为 1.4MB。这意味着仍有约 10 MB 的未解释空间。
答案1
Zip 在压缩时会分别处理每个文件的内容。每个文件都有自己的压缩流。压缩算法中支持该功能(通常放气) 来识别重复的部分。但是,Zip 不支持查找文件之间的冗余。
这就是为什么当内容位于多个文件中时会有这么多额外空间的原因:它将相同的压缩流多次放入文件中。
答案2
ZIP 压缩基于要压缩的数据中的重复模式,文件越长,压缩效果越好,因为可以找到和使用更多更长的模式。
简而言之,如果您压缩一个文件,则将(短)代码映射到(较长)模式的字典必然包含在每个生成的 zip 文件中;如果您压缩一个长文件,则该字典将被“重复使用”,并且在所有内容中变得更加有效。
如果您的文件有一点相似(文本总是如此),那么重新使用“字典”就会变得非常有效,并且结果是总 zip 文件要小得多。
答案3
Zip 中每个文件都是单独压缩的。相反的是“固实压缩”,即文件一起压缩。7-zip 和 Rar 默认使用固实压缩。Gzip 和 Bzip2 无法压缩多个文件,因此首先使用 Tar,其效果与固实压缩相同。
由于 xml 文件具有相似的结构并且可能具有相似的内容,如果将文件一起压缩,则压缩率会更高。
例如,如果一个文件包含字符串"<content><element name="
,并且压缩器已经在另一个文件中找到该字符串,它将用指向前一个匹配项的小指针替换它,如果压缩器不使用“固实压缩”,则文件中第一次出现的字符串将被记录为更大的文字。
答案4
OP 遗漏的一个选项是将所有文件一起压缩并关闭压缩,然后将压缩设置为最大。这大致模拟了 *nix .tar.Z、.tar.gz、.tar.bz 等压缩档案的行为,允许压缩利用跨文件边界的冗余(ZIP 算法在单次运行中无法做到这一点)。这允许稍后提取单个 XML 文件,但最大化压缩。缺点是提取过程需要额外的步骤,暂时使用比普通 .zip 所需的多得多的磁盘空间。
随着 7-Zip 等免费工具的普及,tar 系列扩展到 Windows,真的没有理由不使用 .tar.gz 或 .tar.bz 等,因为 Linux、OS X 和 BSD 都有本机工具来操作它们。