ZIP 简介1989 年引入的 ZIP 文件格式通过删除文件中的空白空间和冗余信息以及把多个文件打成一个包的方式,帮助计算机用户传输大型文件。ZIP 最初是由 Phil Katz 为共享件程序 PKZIP 创建的,ZIP 是一种快速、可靠且遵循开放规范的压缩格式。这些因素使 ZIP 在 PC 用户中大获成功,并且其开放规范使程序员可以把 ZIP 构建到 Windows®、OS X、Konqueror 和 Nautilus 文件管理器中。考虑使用几乎所有计算机都可以处理的 ZIP 文件压缩格式是十分安全的。
压缩通常有很多好处,可以缩小文件大小,也可以把若干个文件绑定为一个归档文件。通过减少文件大小,带宽和存储设备负载也会随之减少。文件大小要求很明显,但是当惟一的其他选择是一个接一个地下载时,能够把若干个文件绑定在一起就是一个巨大的优点。您可以为用户提供把许多单个文件创建为一次下载的功能,使您可以更便捷地把产品或服务交付给用户。
由于几乎所有计算机中都可以使用 ZIP,因此使用它来压缩应用程序是非常好的选择,尤其是在用户将把文件下载到桌面型计算机中时。例如,Windows XP 用户可以便捷地使用本机 ZIP 支持,称为压缩文件夹。当 Windows XP 用户下载 ZIP 文件时,它显示为用户可以双击打开的压缩文件夹。OS X、Konqueror 和 Nautilus 用户也只需双击 ZIP 文件即可打开文件。
被压缩掉的空间去了哪里?被选中放入归档(ZIP 文件的另一个名称)中的文件都列在文件结构中,然后就被缩小或压缩了。文件都是使用众多压缩算法中的一种算法压缩成一个 ZIP 文件的,但这些压缩算法都是以相同的方法操作:删除冗余数据或空白。这种方法在应用到可以减少大量重复文字和标点符号来节省空间的文本文件中时尤为有效。当处理图形文件(例如 JPEG 图像)时,压缩就不那么好用了,因为数据更加难于减少重复。
减少文件大小有若干种方法,并且对于 ZIP 格式,它们全都是常见方法。可以运用 ZIP 的每种语言或每个应用程序都知道这些格式,而且 PHP 也不例外。PHP 将像其他应用程序一样使用这些算法之一来压缩文件,并获得任何其他语言或程序将获得的结果。让我们来看一个示例:
让我们引用我最崇拜的历史人物之一邱吉尔经常说的一段话。文本文件 Winston.txt 包含以下文本:“You make a living by what you get; you make a life by what you give.”。
要压缩文件 Winston.txt,可以删除不必要的空格,方法为创建索引 —— 就像搜索引擎那样操作 —— 并用此索引的副本和索引组件布局的方法清单来替换文件组件。使用像本例这样非常小的示例,如果没有重复的单词,则索引的大小会十分接近示例的大小。仅当单词重复出现时,才能将其添加到索引中,因此这应当不会成为一个问题。
在我们的示例中,有以下重复的单词:
- “we” 使用了四次
- “make” 使用了两次
- “a” 使用了两次
- “by” 使用了两次
- “what” 使用了两次
还剩下几个只需写出的单个单词:
- “living”
- “get”
- “life”
- “give”
如果使用索引写出我们的示例,则得到 “1 2 3 living 4 5 1 get; 1 2 3 life 4 5 1 give.”。
您已经可以看到该文件现在包含的信息要少一些。为了准确,您可以算一下并确定省去了多少字符。原文件共有 64 个字符(包括标点符号)。如果把索引中的注释减少为更简单的内容(如 1we4),则将把索引减少到 23 个字符并加上实际字符串字符总数 33 等于 56。文件大小没有大幅减少,但是如果把演说的其余部分添加到文件中,您将会开始看到压缩中的重大改进。索引将变得更大,但是每个单词的实例数也将增加。索引负载将开始减少,并且您将看到一个优秀的压缩率。
文本文件的压缩率平均为 70% 左右;而对于更复杂更难于压缩的文件(例如图像),其压缩率大约 10%。
ZIP 中有哪些内容?由于 ZIP 归档可以有多个文件,因此 ZIP 归档都有自己的文件结构,就像您的本地计算机的文件系统一样。此结构是围绕条目构建的,并允许巧妙的编码器在解压缩时从许多文件中只选出一个文件。当您只需要归档文件中的一张图片或一个文本文件时,此结构会十分便捷。此结构还将维护目录信息,目录信息在传输 Web 站点或有文件系统关系依赖性的其他文件组时将极为有用。
在 PHP 脚本中,每个文件都有一组可用的文件相关信息。打开文件时,您将能够在创建的 ZipArchive 对象中访问这些信息。这些信息可用于各种目的,例如检验解压缩后的文件大小或只创建 ZIP 文件的内容清单而不打开它。
PHP ZIP 的部分功能允许以十分有用的方法处理这些文件结构。在下一个示例中,我们将展示几种方法查看这些功能并了解如何在创建 ZIP 文件的过程中创建 ZIP 文件结构。
继续压缩让我们再来看一个使用 PHP 创建 ZIP 文件的示例。我将使用的代码示例几乎与 PHP.net 手册文档提供的示例完全相同,只有几处修改(有关 ZIP 功能页面,请参阅 )。让我们浏览一下创建 ZIP 文件的步骤并查看如何正确构建文件结构。我们将把字符串作为文件插入到新 ZIP 中,并把现有文件获取到新 ZIP 中。
首先,需要准备好一个要添加到 ZIP 中的文本文件。
清单 1. testtext.txt1
2
3
4
5
6
7
8
9
10
| Had I the heavens' embroidered cloths,
Enwrought with golden and silver light,
The blue and the dim and the dark cloths
Of night and light and the half-light,
I would spread the cloths under your feet:
But I, being poor, have only my dreams;
I have spread my dreams under your feet,
Tread softly because you tread on my dreams.
William Butler Yeats
|
您可以测试这段代码以直接查看这次尝试的结果。如果要测试,应当剪切和粘贴清单 1,并将它与 PHP 脚本放在同一目录下。将此文件另存为 testtext.txt,因为将在 PHP 代码中引用此名称。
接下来,需要创建 ZIP 文件。
清单 2. zipcreate.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| <?php
$zip = new ZipArchive();
$filename = "newzip.zip";
if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) {
exit("cannot open <$filename>\n");
}
$zip->addFromString("firstfile." . time() . ".txt", \
"This is the first file in our ZIP, added as
firstfile.txt.\n");
$zip->addFromString("testdir/secondfile." . time() . ".txt", \
"This is the second file in our ZIP,
added as secondfile.txt in the testdir directory.\n");
echo "numfiles: " . $zip->numFiles . "\n";
$zip->close();
?>
|
首先在第一行中创建新的 ZIP 归档对象。创建了对象后,将为文件名设置一个变量,以供稍后在脚本中使用。可以每次都显式调用该文件名,但是设置一个变量以供多次使用会更轻松。常量 ZIPARCHIVE::CREATE 表示如果具有该名称的文件尚不存在,则应当创建一个新文件。如果这是您第一次运行脚本,将新建 ZIP 文件。如果这个结果没有出现,脚本将显示错误并退出。
接下来,使用 addFromString() 方法,该方法允许您使用字符串数据或通过字符串变量在 ZIP 归档中创建条目。需要创建文件句柄,才能在 ZIP 文件结构中识别文件。在这种情况下,使用了 firstfile.txt 作为文件名,同时还使用了它的创建时间。字符串数据随后被存储。接下来在处理 secondfile.txt 时将再执行一次该操作,但是这次我们添加了目录。您可以看到文件标识符 secondfile.txt 实际上列有路径的下一级。它将显示在 testdir 目录中。 |