总算到了 PHP 的拿手好戏上场了,后面咱们学习过 Bzip2、LZF、Phar 和 rar 这些压缩相干扩大在 PHP 中的应用,不过它们要么是太冷门,要么就是很多性能不反对。而 Zip 则是在 PHP 中失去最大幅度性能反对的热门压缩格局,或者说是通用常见的一种压缩格局。当然,也次要得益于 Zip 也是事实上的 Linux 环境中的通用压缩格局。
装置
对于 PHP 来说,Zip 扩大曾经集成在了 PHP 的安装包中,在 Configure 的时候能够间接加上 –with-zip,如果在装置的时候没有加上这个参数,咱们也能够在源码包的 ext/zip 下找到源码,而后通过扩大装置的形式进行装置。
创立一个压缩包
$zip = new ZipArchive();
$filename = './test_zip.zip';
if($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE){exit('cannot open' . $filename .'\n');
}
// 退出文字类型的文件
$zip->addFromString('testfile1.txt' . time(), "#1");
$zip->addFromString('testfile2.txt' . time(), "#2");
// 退出已存在的文件
$zip->addFile('rar.php', 'newrar.php');
echo $zip->numFiles, PHP_EOL; // 文件数量
echo $zip->status, PHP_EOL; // 压缩包状态
$zip->close();
// 应用操作系统的 unzip 查看
// # unzip -l test_zip.zip
// Archive: test_zip.zip
// Length Date Time Name
// --------- ---------- ----- ----
// 2 07-08-2020 08:57 testfile1.txt1594169845
// 2 07-08-2020 08:57 testfile2.txt1594169845
// 2178 07-07-2020 08:55 newrar2.php
// --------- -------
// 2182 3 files
之前学习过的 rar 扩大是无奈打包文件或者创立新的压缩包的,而 Zip 一上来咱们就学习的是创立一个新的压缩包。通过实例化一个 ZipArchive 对象后,咱们就能够应用 open() 函数关上或创立一个压缩包文件。接着,咱们应用了两种增加内容的形式。addFromString() 是退出文字类型的文件,也就是将一段文字转换成文本文件保留在这个压缩包中。另外,咱们通过 addFile() 来将内部的文件退出到这个压缩包中。
numFiles 和 status 属性能够别离查看到压缩包文件外面的文件数量及以后这个压缩包的状态信息。最初间接应用 close() 敞开句柄即可。这样,一个简略的 Zip 压缩包文件就创立实现了。咱们能够间接应用操作系统的 unzip 命令来查看压缩包的内容。
读取压缩包内容及信息
$zip = new ZipArchive();
$zip->open('./test_zip.zip');
print_r($zip); // 压缩包信息
// ZipArchive Object
// (// [status] => 0
// [statusSys] => 0
// [numFiles] => 40
// [filename] => /data/www/blog/test_zip.zip
// [comment] =>
// )
var_dump($zip);
// object(ZipArchive)#2 (5) {// ["status"]=>
// int(0)
// ["statusSys"]=>
// int(0)
// ["numFiles"]=>
// int(40)
// ["filename"]=>
// string(27) "/data/www/blog/test_zip.zip"
// ["comment"]=>
// string(0) ""
// }
echo $zip->numFiles, PHP_EOL;
echo $zip->status, PHP_EOL;
echo $zip->statusSys, PHP_EOL;
echo $zip->filename, PHP_EOL;
echo $zip->comment, PHP_EOL;
echo $zip->count(), PHP_EOL;
for ($i=0; $i<$zip->numFiles;$i++) {
echo "index: $i\n";
// 打印每个文件实体信息
print_r($zip->statIndex($i));
// index: 0
// Array
// (// [name] => testfile1.txt1594169845
// [index] => 0
// [crc] => 2930664868
// [size] => 2
// [mtime] => 1594169844
// [comp_size] => 2
// [comp_method] => 0
// [encryption_method] => 0
// )
// ……
$entry = $zip->statIndex($i);
if($entry['name'] == 'newrar.php'){
// 仅解压 newrar.php 文件到指定目录
$zip->extractTo('./test_zip_single', $entry['name']);
}
}
// 批改压缩包内的文件名
$zip->renameName('newrar.php', 'newrar2.php');
print_r($zip->getFromIndex(2)); // 获取第二个文件的内容
print_r($zip->getFromName('newrar2.php')); // 获取指定文件名的文件内容
$zip->extractTo('./test_zip'); // 解压整个压缩包到指定目录
$zip->close();
其实读取也是同样的步骤,实例化一个 ZipArchive 类,而后 open() 关上一个压缩包文件句柄。接着就能够间接输入一些压缩包的属性信息。咱们能够通过循环并通过 statIndex() 办法获取每个文件实体的信息。这里须要留神的是 statIndex() 获取的是文件的信息,而不是这个文件的内容。
当然,咱们也能够通过 getFromIndex() 或 getFromName() 间接获取指定的文件。通过 renameName() 间接给压缩包外部的文件改名,通过 extractTo() 将指定的文件或者整个压缩包解压到指定的目录中。extractTo() 办法的第二个参数如果指定了内容,则只会解压指定的这个文件。
压缩目录,设置阐明以及流、伪协定形式读取文件
既然是压缩包工具,那么咱们最罕用的也就是间接将多个文件或者目录进行打包。同时,也有很多压缩包能够设置一些阐明、明码什么的。另外,咱们还能够通过专属的 zip:// 伪协定来间接获取压缩包内某个文件的内容。这些性能,在 PHP 的 Zip 扩大中都可能非常简单不便地应用。
压缩目录
// 压缩目录
$zip = new ZipArchive();
$zip->open('./test_zip2.zip', ZIPARCHIVE::CREATE);
$zip->addFile('rar.php', 'newrar.php');
$zip->addGlob('./test_zip/*.{php,txt}', GLOB_BRACE, ['add_path'=> 'new_path/']);
间接应用 addGlob 就能够帮忙咱们实现对某个文件目录下的所有文件的内容打包。同时,它的第三个参数也能够指定这些文件在压缩包外部的门路地址。
设置阐明及明码
// 设置正文、明码
$zip->setArchiveComment('This is rar Comment!');
$zip->setPassword('123');
$zip->close();
// 应用操作系统 unzip 查看
// # unzip -l test_zip2.zip
// Archive: test_zip2.zip
// This is rar Comment!
// Length Date Time Name
// --------- ---------- ----- ----
// 2178 07-07-2020 08:55 newrar.php
// 2178 07-08-2020 10:36 new_path/./test_zip/newrar.php
// 2178 07-08-2020 10:36 new_path/./test_zip/newrar2.php
// --------- -------
// 6534 3 files
设置压缩包的阐明正文以及明码都是有现成的函数办法间接应用的。咱们再次通过操作系统的 unzip 命令,就能够查看到这个压缩包的正文信息以及打包的目录内容。原本测试的 test_zip/ 目录下的内容被放在了 new_path/ 目录下,这就是咱们自定的一个压缩包外部的门路地址。
流、伪协定形式读取文件
// 流、伪协定办法读取压缩包内容
$zip = new ZipArchive();
$zip->open('./test_zip2.zip');
// 获取文件流
$fp = $zip->getStream('newrar.php');
while(!feof($fp)){echo fread($fp, 2);
}
fclose($fp);
// 应用伪协定
$fp = fopen('zip://' . dirname(__FILE__) . '/test_zip2.zip#newrar.php', 'r');
while(!feof($fp)){echo fread($fp, 2);
}
fclose($fp);
// file_get_contents 应用伪协定
echo file_get_contents('zip://' . dirname(__FILE__) . '/test_zip2.zip#newrar.php');
// 间接应用伪协定将文件拷贝进去
copy('zip://' . dirname(__FILE__) . '/test_zip2.zip#newrar.php', './newrar2.php');
首先,咱们通过 getStream() 办法间接获取压缩包中某个文件的流,这种形式简直是所有压缩类扩大都会提供的一种读取文件的形式。而上面的形式则是通过 zip:// 伪协定间接应用 fopen()、file_get_contents() 函数来读取压缩包外部的某个文件。既然有了这么不便的一个伪协定,那么咱们要简略的获取并解压某个文件也就变得非常容易了,间接应用 copy() 函数将这个文件拷贝进去就能够了。
总结
是不是感觉比 rar 的操作弱小了许多。都说了这是 PHP 主力反对的一种通用压缩格局,所以当然性能会丰盛许多,而且还有很多的函数办法咱们并没有全部列进去,如果全列出来的话还不如大家本人去看手册呢。这里就是以一些简略的例子让大家看到这类扩大性能的操作,不便大家在业务选型的时候可能疾速的联想到咱们 PHP 就曾经提供了这些现成的扩大。须要理解 Zip 其它内容的同学能够移步最下方的链接间接进入手册中查阅。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202007/source/PHP%E7%9A%84zip%E5%8E%8B%E7%BC%A9%E5%B7%A5%E5%85%B7%E6%89%A9%E5%B1%95%E5%8C%85%E5%AD%A6%E4%B9%A0.php
参考文档:
https://www.php.net/manual/zh/book.zip.php
各自媒体平台均可搜寻【硬核项目经理】