总算到了咱们压缩相关扩展的最后一篇文章了,最后咱们要学习的也是 Linux 下很是经常使用的一种压缩格式:.gz 的压缩扩展。做为 PHP 的自带扩展,就像 zip 同样,zlib 扩展是随着 PHP 的安装包一块儿发布的,因此咱们在编译的时候直接加上 --with-zlib 就能够了,若是没法找到对应的软件包的话,使用 yum 安装相应的软件包便可。php
// 建立压缩包 $zp = gzopen('./gztest.gz', "w9"); gzwrite($zp, "Only test, test, test, test, test, test!\n"); gzclose($zp);
压缩包的建立很是地简单,不过 PHP 的这个扩展中,只能使用 gzwrite() 来建立这种字符串类型的压缩包,没法直接将某些目录或者文件进行打包。html
建立压缩包成功后,咱们就能够经过系统的 tar 命令来解压或者查看文件了。git
// 读取压缩包 $zp = gzopen('./gztest.gz', "r"); echo gzread($zp, 3); gzpassthru($zp); // 输出 gz 文件指针中的全部剩余数据 // Only test, test, test, test, test, test! echo PHP_EOL; gzpassthru($zp); // gzrewind($zp); // 将 gz 指针的游标返回到最开始的位置 gzpassthru($zp); // Only test, test, test, test, test, test! echo PHP_EOL; gzclose($zp);
读取操做其实也很是简单,直接使用 gzpassthru() 就能够输出当前压缩包里面的内容,而且是直接打印出来。固然,它也是以相似于文件指针的形式进行输出的,因此若是咱们输出过一次以后,就必需要使用 gzrewind() 将指针的游标还原到句柄最开始的位置。程序员
对于 zlib 的压缩包来讲,咱们还有不少其它的方式能够进行文件内容的读取。github
// 读取压缩包二 $gz = gzopen('./gztest.gz', 'r'); while (!gzeof($gz)) { echo gzgetc($gz); } gzclose($gz); // Only test, test, test, test, test, test! echo PHP_EOL; // 读取压缩包三 echo readgzfile("./gztest.gz"); // Only test, test, test, test, test, test! echo PHP_EOL; // 读取压缩包四 print_r(gzfile("./gztest.gz")); // Array // ( // [0] => Only test, test, test, test, test, test! // ) echo PHP_EOL;
这里一口气就提供了三种读取的方式。首先固然仍是咱们最熟悉的文件操做形式的读取,使用的是 zlib 为咱们提供的 gzeof() 和 gzgetc() 函数。除了 gzgetc() 以外,也提供了包括 gzgets() 和 gzgetss() ,分别是按行和按 HTML 格式行的读取。其次,咱们可使用 readgzfile() 来直接读取整个压缩文件的内容,连 gzopen() 均可以省了,与它相似的是 gzfile() 函数,这个函数与 readgzfile() 的区别就是它读取的内容是以数组形式返回的,对于多文件的压缩包更有用。算法
既然 zlib 所压缩的格式是 .gz 类型,并且还只能作字符串形式的压缩,那么很多小伙伴确定有疑问了,它和 gzip 有什么关系呢?其实,zlib 除了是能够作为压缩打包工具以外,也能够作为 gzip 工具应用到咱们的服务器中。固然,如今大多数状况下咱们只须要开启 Nginx 或者 Apache 的 gzip 压缩功能就能够了,不须要咱们再到 PHP 中进行处理了。不过作为一名合格的 PHP 程序员,相关的操做函数咱们仍是须要学习的,说不定哪天就用上了呢。数组
// 压缩类型及相关操做 // gzcompress 默认使用ZLIB_ENCODING_DEFLATE编码,使用zlib压缩格式,其实是用 deflate 压缩数据,而后加上 zlib 头和 CRC 校验 $compressed = gzcompress('Compress me', 9); echo $compressed; // x�s��-(J-.V�M�? echo PHP_EOL; echo gzuncompress($compressed); // Compress me echo PHP_EOL; // gzencode 默认使用ZLIB_ENCODING_GZIP编码,使用gzip压缩格式,其实是使用defalte 算法压缩数据,而后加上文件头和adler32校验 $compressed = gzencode('Compress me', 9); echo $compressed; // s��-(J-.V�M�jM4 echo PHP_EOL; echo gzdecode($compressed); // Compress me echo PHP_EOL; // gzdeflate 默认使用ZLIB_ENCODING_RAW编码方式,使用deflate数据压缩算法,其实是先用 LZ77 压缩,而后用霍夫曼编码压缩 $compressed = gzdeflate('Compress me', 9); echo $compressed; // s��-(J-.V�M echo PHP_EOL; echo gzinflate($compressed); // Compress me echo PHP_EOL;
其实注释中已经写得很清晰了,不止是 PHP ,Nginx 也是会提供这三种编码格式的,并且咱们从浏览器中就能够看出当前访问的网站使用的是哪一种压缩编码格式。好比咱们访问 PHP 的官方网站所返回的内容:浏览器
从性能的维度看:deflate 好于 gzip 好于 zlib,而从文本文件默认压缩率压缩后体积的维度看:deflate 好于 zlib 好于 gzip 。也就是说,deflate 格式无论在性能仍是压缩率来讲都是如今比较好的选择。固然,这样好的格式对于 CPU 的硬件性能的影响就不清楚了,毕竟咱们没有大型的功能页面来进行测试,起码对于普通的网站页面来讲,已经绰绰有余了。服务器
另外,就像其它的压缩工具同样,可以对于字符串进行编码的工具咱们均可以扩展一个应用场景,那就是数据的加密能力,这个在前面 Bzip2 、 LZF 相关的这些文章已经说过了,就再也不多说了。函数
最后,咱们还有一个通用的函数经过预约义的常量直接能够操做这三种类型的编码及解码。
// 通用压缩函数 $compressed = zlib_encode('Compress me', ZLIB_ENCODING_GZIP, 9); echo $compressed; // ZLIB_ENCODING_RAW:s��-(J-.V�M // ZLIB_ENCODING_DEFLATE:x�s��-(J-.V�M�? // ZLIB_ENCODING_GZIP:s��-(J-.V�M�jM4 echo PHP_EOL; echo zlib_get_coding_type(); echo PHP_EOL; echo zlib_decode($compressed); // Compress me echo PHP_EOL;
zlib_encode() 函数的第二个参数就是须要指定一个编码的类型,这里 zlib 扩展已经为咱们准备好了 ZLIB_ENCODING_RAW 、 ZLIB_ENCODING_DEFLATE 、 ZLIB_ENCODING_GZIP 这三个类型的常量。而解压 zlib_decode() 则不须要再进行指定了,它会直接根据文件头自动选择相应的编码格式对内容进行解码。
在 PHP7 中,zlib 扩展为咱们增长一种能够增量压缩编码的操做函数,就是能够在不使用对象句柄的状况下,使用函数直接增长内容。
// PHP7 新增的增量压缩操做函数 $deflateContext = deflate_init(ZLIB_ENCODING_GZIP); $compressed = deflate_add($deflateContext, "数据压缩", ZLIB_NO_FLUSH); $compressed .= deflate_add($deflateContext, ",更多数据", ZLIB_NO_FLUSH); $compressed .= deflate_add($deflateContext, ",继续添加更多数据!", ZLIB_FINISH); // ZLIB_FINISH 终止 echo $compressed, PHP_EOL; // {6uó�uO����Y�~Oϳ�[�.�� // �>߽���϶�~ڵU�h�9 $inflateContext = inflate_init(ZLIB_ENCODING_GZIP); $uncompressed = inflate_add($inflateContext, $compressed, ZLIB_NO_FLUSH); $uncompressed .= inflate_add($inflateContext, NULL, ZLIB_FINISH); echo $uncompressed; // 数据压缩,更多数据,继续添加更多数据!
就像例子中展现的那样,deflate_add() 用于增量的添加内容到编码文件中,当标志为 ZLIB_FINISH 时结束操做的写入。deflate_init() 和 inflate_init() 分别是编码和反编码对应的初始化操做。
关于压缩解压相关的扩展咱们已经介绍了 Bzip2 、 LZF 、 Phar 、 rar 、 zip 和 zlib 这些官方的扩展,在实际的生产中咱们其实会比较经常使用到的是 zip 和 zlib ,固然,对于其它的格式也有了必定的学习了解,剩下的就是咱们本身在用到的时候再次的深度研究了。这一个系列的内容让我对这些压缩格式也有了更一步的了解,但愿你们也能从中获益。
测试代码:
参考文档:
https://www.php.net/manual/zh/book.zlib.php
各自媒体平台都可搜索【硬核项目经理】