共计 4313 个字符,预计需要花费 11 分钟才能阅读完成。
总算到了咱们压缩相干扩大的最初一篇文章了,最初咱们要学习的也是 Linux 下十分罕用的一种压缩格局:.gz 的压缩扩大。作为 PHP 的自带扩大,就像 zip 一样,zlib 扩大是随着 PHP 的安装包一起公布的,所以咱们在编译的时候间接加上 –with-zlib 就能够了,如果无奈找到对应的软件包的话,应用 yum 装置相应的软件包即可。
创立压缩包
// 创立压缩包
$zp = gzopen('./gztest.gz', "w9");
gzwrite($zp, "Only test, test, test, test, test, test!\n");
gzclose($zp);
压缩包的创立十分地简略,不过 PHP 的这个扩大中,只能应用 gzwrite() 来创立这种字符串类型的压缩包,无奈间接将某些目录或者文件进行打包。
创立压缩包胜利后,咱们就能够通过零碎的 tar 命令来解压或者查看文件了。
读取压缩包内容
// 读取压缩包
$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 的压缩包来说,咱们还有很多其它的形式能够进行文件内容的读取。
// 读取压缩包二
$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() 的区别就是它读取的内容是以数组模式返回的,对于多文件的压缩包更有用。
gzip 压缩类型
既然 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://github.com/zhangyue0503/dev-blog/blob/master/php/202007/source/PHP%E7%9A%84zlib%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.zlib.php
https://www.php.cn/php-weizijiaocheng-377246.html
各自媒体平台均可搜寻【硬核项目经理】