PHP V5.2 中的新增功能,第 4 部分: 使用新的 ZIP 扩展

来源:百度文库 编辑:神马文学网 时间:2024/05/02 10:07:47

ZIP 简介

1989年引入的 ZIP 文件格式通过删除文件中的空白空间和冗余信息以及把多个文件打成一个包的方式,帮助计算机用户传输大型文件。ZIP 最初是由Phil Katz 为共享件程序 PKZIP 创建的,ZIP 是一种快速、可靠且遵循开放规范的压缩格式。这些因素使 ZIP 在 PC用户中大获成功,并且其开放规范使程序员可以把 ZIP 构建到 Windows®、OS X、Konqueror 和 Nautilus文件管理器中。考虑使用几乎所有计算机都可以处理的 ZIP 文件压缩格式是十分安全的。

压缩通常有很多好处,可以缩小文件大小,也可以把若干个文件绑定为一个归档文件。通过减少文件大小,带宽和存储设备负载也会随之减少。文件大小要求很明显,但是当惟一的其他选择是一个接一个地下载时,能够把若干个文件绑定在一起就是一个巨大的优点。您可以为用户提供把许多单个文件创建为一次下载的功能,使您可以更便捷地把产品或服务交付给用户。

由于几乎所有计算机中都可以使用ZIP,因此使用它来压缩应用程序是非常好的选择,尤其是在用户将把文件下载到桌面型计算机中时。例如,Windows XP 用户可以便捷地使用本机ZIP 支持,称为压缩文件夹。当 Windows XP 用户下载 ZIP 文件时,它显示为用户可以双击打开的压缩文件夹。OSX、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,可以删除不必要的空格,方法为创建索引 —— 就像搜索引擎那样操作 ——并用此索引的副本和索引组件布局的方法清单来替换文件组件。使用像本例这样非常小的示例,如果没有重复的单词,则索引的大小会十分接近示例的大小。仅当单词重复出现时,才能将其添加到索引中,因此这应当不会成为一个问题。

在我们的示例中,有以下重复的单词:

  1. “we” 使用了四次
  2. “make” 使用了两次
  3. “a” 使用了两次
  4. “by” 使用了两次
  5. “what” 使用了两次

还剩下几个只需写出的单个单词:

  1. “living”
  2. “get”
  3. “life”
  4. “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.txt
                
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.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 目录中。

我们向用户展示归档中的文件数并关闭文件,将其保存为 ZIP 归档,准备供用户下载。您可能会注意到在连续按 Refresh 或用其他方法运行 PHP 脚本时,ZIP 中的文件数会增长。这是因为一直在打开同一个目录中的同一个文件,添加两个字符串作为文件,并再次关闭。


图 1. zipcreate.php 的样例输出


正如您会注意到的,实际上并未把新文件添加到 ZIP 中。我们需要把诗歌放在其中,以便用户获得一些训练。让我们现在就来添加。


清单 3. 将外部文件添加到 newzip.zip 中
                
$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.\n");
$zip->addFile("testtext.txt");
echo "numfiles: " . $zip->numFiles . "\n";
$zip->close();
?>

这样看来,路径是相对的,只是指向了需要添加到 ZIP 中的文件并使用 addFile() 方法把它打包在其中。如果文件 testtext.txt 位于同一个目录中,这样做可以将其添加到归档中。现在已经通过任意的字符串数据创建了新归档文件并已经把外部文件添加到了归档中。这些都是创建新归档时最常见的任务。





回页首

打开归档

如果我们不能从归档中恢复出可正常使用的文件,那么 ZIP文件就没有多大用处。一些程序可以把文件直接从归档中读出,但是这些程序必须先把文件解压缩。最常见的处理方法是,简单地打开整个文件并将其展开为单个组件文件,把这些文件准备好以供正常使用。出于我们的目的,将打开先前创建的 ZIP 文件并查看其内容。


清单 4. zipread.php
                
$zip = new ZipArchive();
$filename = ‘newzip.zip‘;

if ($zip->open($filename)!==TRUE) {
exit("cannot open <$filename>\n");
}

print_r($zip);
var_dump($zip);

echo "

";
echo "The file " .$filename. " has the following files:\n
";

for ($i=0; $i<$zip->numFiles;$i++) {
echo "index: $i\n";
print_r($zip->statIndex($i));
echo "
\n";
}

$zip->extractTo(‘./testdestination/‘);

$zip->close();
?>

像以前一样,在名为 $zip 的变量表单中创建 ZipArchive 类的新实例。使用 ZipArchiveopen() 方法,打开已创建的 ZIP 归档。if 语句将用作简单的错误控制,如果由于用户的小失误而导致它未找到文件,则退出脚本。如果成功打开文件,脚本将继续执行并把关于 ZIP 归档的一些信息打印给用户。

到此为止,我们完成了两项重要任务。逐个列出了 ZIP 归档中的文件。由于将从 $zip 对象输出索引数组,因此将获得大量数据,包括文件大小、校验和信息。要减少数据量,在特定索引中查看文件的各个属性即可。

一旦打印出文件中的内容,所有内容就会被释放到名为 testdestination 的目录中。如果此目录不可用,系统将为我们创建该目录。此时需要注意的是如果目录已存在,或者如果解压缩的目标目录中已经有同名文件,则 ZIP 函数将覆盖原有内容。

我们已经打开了 ZIP 归档,通过保存到本地目录为使用文件做好了准备,并且列出了内容,可为修改初始的 ZIP文件做好准备。这些简单的任务只是一个开始,并且几乎不能用于最复杂应用程序的文件压缩。巧妙地使用压缩可以为所有类型的文件传输带来更多便利。PHP中的 ZIP 本机支持将使大量文件传输问题得以解决。





回页首

结束语

在处理拥有大量空白或重复数据的大型文件时,ZIP是一种十分优秀方法,能够降低带宽负载或存储设备使用量。我们可以清理掉文件中的大量冗余或空白,并使其减少到只包含基本要素,从而使文件更加紧凑。这样做都可以明显地减少文件在文件系统中占用的空间大小以及移动文件时所需的全部带宽负载。

一种可能的应用是在需要把大量文件上传到服务器上时,比如需要把照片上传到照片库中或上传许多文本文件。您可以简单地 ZIP 文件并同样让上传脚本将文件解压缩,而不用费力地在上传对话框中逐个上传文件。这可以免去必须单击 Browse 对话框的痛苦。

一般而言,ZIP 那些不会被直接访问的文件或者下载后再使用的文件是个好主意 —— 并且我们最终使 PHP 拥有了这种功能。



参考资料

学习
  • 阅读本系列的 第 1 部分、第 2 部分 和 第 3 部分。

  • 阅读 PHP 5.2.0 发行说明。

  • 从 PHP.net 获得 ZIP 文件函数 的参考资料。

  • 可在 W3School.com 获得 PHP ZIP 文件函数 的其他参考资料。

  • 从 Zend Developer Zone 获得 Zend 提供的 ZIP 在 PHP 中应用的参考资料。

  • “A step-by-step how-to guide to install, configure, and test a Linux, Apache, Informix, and PHP server” 包含关于如何针对 Linux 编译 PHP 解释程序的部分。

  • 在 “PHP V5 迁移指南” 中了解如何将在 PHP V4 中开发的代码移植到 PHP V5 中。

  • 要获得学习使用 PHP 进行编程的教程,请查看 developerWorks 的 “学习 PHP” 系列。

  • Planet PHP 是 PHP 开发者社区新闻资源。

  • PHP.net 是 PHP 开发者的资源。

  • 查阅“PHP 推荐读物列表”。

  • 浏览 developerWorks 上的所有 PHP 文章 和 PHP 教程。

  • 查看 IBM developerWorks 的 PHP 项目资源 扩展 PHP 技巧。

  • 收听针对软件开发人员的有趣访谈和讨论,一定要访问 developerWorks podcast。

  • 随时关注 developerWorks 的 技术事件和网络广播。

  • 要将数据库与 PHP 结合使用?查看 Zend Core for IBM,它是支持 IBM DB2 9 的无缝、即用且易于安装的 PHP 开发和生产环境。

  • 查阅最近将在全球举办的面向 IBM 开放源码开发人员的研讨会、展览、网络广播和其他 活动。

  • 访问 developerWorks 开放源码专区,获得丰富的 how-to 信息、工具和项目更新,帮助您用开放源码技术进行开发,并与 IBM 产品结合使用。

PHP V5.2 中的新增功能,第 4 部分: 使用新的 ZIP 扩展 PHP V5.2 中的新增功能,第 4 部分: 使用新的 ZIP 扩展 PHP V5.2 中的新增功能,第 3 部分: 使用新的 JSON 扩展 PHP V5.2 中的新增功能,第 2 部分: 使用新输入过滤扩展功能 PHP V5.2 中的新增功能,第 1 部分: 使用新的内存管理器 PHP V5.2 中的新增功能,第 1 部分: 使用新的内存管理器 PHP V5.2 中的新增功能,第 5 部分: 跟踪文件上传进度 使用 PHP 和 DHTML 设计 Web 2.0 应用程序,第 1 部分: 使用这些技术打造有特色的应用 使用 PHP 和 DHTML 设计 Web 2.0 应用程序,第 2 部分: 使用 JavaScript 创建 HTML 动态元素 使用 PHP 和 DHTML 设计 Web 2.0 应用程序,第 2 部分: 使用 JavaScript 创建 HTML 动态元素 phplibclamav-PHP的杀毒扩展 php-5.x.x-Win32.zip的组织 PHP的GZIP压缩页面例子,使用zlib扩展实现页面GZIP压缩输出 hello world: websphere portal v5 最简单的 portlet:第 1 部分,创建和部署 hello world: websphere portal v5 最简单的 portlet:第 1 部分,创建和部署 审计 PHP,第 1 部分: 理解 register_globals 审计 PHP,第 1 部分: 理解 register_globals Google 官方发布在任意网站使用 Google Scribe 功能的扩展 PowerPoint功能扩展的几个常用方法2 Office 2010 的新增功能 Office 2010 的新增功能 Photoshop CS5新增功能实例精解(一)第二部分 7-zip新的压缩选择 - zmxj的专栏 WebSphere Application Server Community Edition 中的高级管理,第 2 部分: 使用线程池、集群和配置插件