日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

PHP的zlib壓縮工具擴展包學(xué)習(xí)

 硬核項目經(jīng)理 2021-05-31

PHP的zlib壓縮工具擴展包學(xué)習(xí)

總算到了我們壓縮相關(guān)擴展的最后一篇文章了,最后我們要學(xué)習(xí)的也是 Linux 下非常常用的一種壓縮格式:.gz 的壓縮擴展。作為 PHP 的自帶擴展,就像 zip 一樣,zlib 擴展是隨著 PHP 的安裝包一起發(fā)布的,所以我們在編譯的時候直接加上 --with-zlib 就可以了,如果無法找到對應(yīng)的軟件包的話,使用 yum 安裝相應(yīng)的軟件包即可。

創(chuàng)建壓縮包

// 創(chuàng)建壓縮包
$zp = gzopen('./gztest.gz'"w9");

gzwrite($zp, "Only test, test, test, test, test, test!\n");

gzclose($zp);

壓縮包的創(chuàng)建非常地簡單,不過 PHP 的這個擴展中,只能使用 gzwrite() 來創(chuàng)建這種字符串類型的壓縮包,無法直接將某些目錄或者文件進行打包。

創(chuàng)建壓縮包成功后,我們就可以通過系統(tǒng)的 tar 命令來解壓或者查看文件了。

讀取壓縮包內(nèi)容

// 讀取壓縮包
$zp = gzopen('./gztest.gz'"r");

echo gzread($zp, 3);

gzpassthru($zp); // 輸出 gz 文件指針中的所有剩余數(shù)據(jù)
// 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() 就可以輸出當(dāng)前壓縮包里面的內(nèi)容,并且是直接打印出來。當(dāng)然,它也是以類似于文件指針的形式進行輸出的,所以如果我們輸出過一次之后,就必須要使用 gzrewind() 將指針的游標還原到句柄最開始的位置。

對于 zlib 的壓縮包來說,我們還有很多其它的方式可以進行文件內(nèi)容的讀取。

// 讀取壓縮包二
$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;

這里一口氣就提供了三種讀取的方式。首先當(dāng)然還是我們最熟悉的文件操作形式的讀取,使用的是 zlib 為我們提供的 gzeof() 和 gzgetc() 函數(shù)。除了 gzgetc() 之外,也提供了包括 gzgets() 和 gzgetss() ,分別是按行和按 HTML 格式行的讀取。其次,我們可以使用 readgzfile() 來直接讀取整個壓縮文件的內(nèi)容,連 gzopen() 都可以省了,與它類似的是 gzfile() 函數(shù),這個函數(shù)與 readgzfile() 的區(qū)別就是它讀取的內(nèi)容是以數(shù)組形式返回的,對于多文件的壓縮包更有用。

gzip 壓縮類型

既然 zlib 所壓縮的格式是 .gz 類型,而且還只能做字符串形式的壓縮,那么不少小伙伴肯定有疑問了,它和 gzip 有什么關(guān)系呢?其實,zlib 除了是可以做為壓縮打包工具之外,也可以做為 gzip 工具應(yīng)用到我們的服務(wù)器中。當(dāng)然,現(xiàn)在大多數(shù)情況下我們只需要開啟 Nginx 或者 Apache 的 gzip 壓縮功能就可以了,不需要我們再到 PHP 中進行處理了。不過做為一名合格的 PHP 程序員,相關(guān)的操作函數(shù)我們還是需要學(xué)習(xí)的,說不定哪天就用上了呢。

// 壓縮類型及相關(guān)操作
// gzcompress 默認使用ZLIB_ENCODING_DEFLATE編碼,使用zlib壓縮格式,實際上是用 deflate 壓縮數(shù)據(jù),然后加上 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 算法壓縮數(shù)據(jù),然后加上文件頭和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數(shù)據(jù)壓縮算法,實際上是先用 LZ77 壓縮,然后用霍夫曼編碼壓縮
$compressed = gzdeflate('Compress me'9);
echo $compressed;
// s??-(J-.V?M
echo PHP_EOL;

echo gzinflate($compressed);
// Compress me
echo PHP_EOL;

其實注釋中已經(jīng)寫得很清晰了,不止是 PHP ,Nginx 也是會提供這三種編碼格式的,而且我們從瀏覽器中就可以看出當(dāng)前訪問的網(wǎng)站使用的是哪種壓縮編碼格式。比如我們訪問 PHP 的官方網(wǎng)站所返回的內(nèi)容:

從性能的維度看:deflate 好于 gzip 好于 zlib,而從文本文件默認壓縮率壓縮后體積的維度看:deflate 好于 zlib 好于 gzip 。也就是說,deflate 格式不管在性能還是壓縮率來說都是現(xiàn)在比較好的選擇。當(dāng)然,這樣好的格式對于 CPU 的硬件性能的影響就不清楚了,畢竟我們沒有大型的功能頁面來進行測試,起碼對于普通的網(wǎng)站頁面來說,已經(jīng)綽綽有余了。

另外,就像其它的壓縮工具一樣,能夠?qū)τ谧址M行編碼的工具我們都可以擴展一個應(yīng)用場景,那就是數(shù)據(jù)的加密能力,這個在前面 Bzip2 、 LZF 相關(guān)的這些文章已經(jīng)說過了,就不再多說了。

最后,我們還有一個通用的函數(shù)通過預(yù)定義的常量直接可以操作這三種類型的編碼及解碼。

// 通用壓縮函數(shù)
$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() 函數(shù)的第二個參數(shù)就是需要指定一個編碼的類型,這里 zlib 擴展已經(jīng)為我們準備好了 ZLIB_ENCODING_RAW 、 ZLIB_ENCODING_DEFLATE 、 ZLIB_ENCODING_GZIP 這三個類型的常量。而解壓 zlib_decode() 則不需要再進行指定了,它會直接根據(jù)文件頭自動選擇相應(yīng)的編碼格式對內(nèi)容進行解碼。

增量壓縮操作函數(shù)

在 PHP7 中,zlib 擴展為我們增加一種可以增量壓縮編碼的操作函數(shù),就是可以在不使用對象句柄的情況下,使用函數(shù)直接增加內(nèi)容。

// PHP7 新增的增量壓縮操作函數(shù)
$deflateContext = deflate_init(ZLIB_ENCODING_GZIP);
$compressed = deflate_add($deflateContext, "數(shù)據(jù)壓縮", ZLIB_NO_FLUSH);
$compressed .= deflate_add($deflateContext, ",更多數(shù)據(jù)", ZLIB_NO_FLUSH);
$compressed .= deflate_add($deflateContext, ",繼續(xù)添加更多數(shù)據(jù)!", 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;
// 數(shù)據(jù)壓縮,更多數(shù)據(jù),繼續(xù)添加更多數(shù)據(jù)!

就像例子中展示的那樣,deflate_add() 用于增量的添加內(nèi)容到編碼文件中,當(dāng)標志為 ZLIB_FINISH 時結(jié)束操作的寫入。deflate_init() 和 inflate_init() 分別是編碼和反編碼對應(yīng)的初始化操作。

總結(jié)

關(guān)于壓縮解壓相關(guān)的擴展我們已經(jīng)介紹了 Bzip2 、 LZF 、 Phar 、 rar 、 zip 和 zlib 這些官方的擴展,在實際的生產(chǎn)中我們其實會比較常用到的是 zip 和 zlib ,當(dāng)然,對于其它的格式也有了一定的學(xué)習(xí)了解,剩下的就是我們自己在用到的時候再次的深度研究了。這一個系列的內(nèi)容讓我對這些壓縮格式也有了更一步的了解,希望大家也能從中獲益。

測試代碼:

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./manual/zh/book.zlib.php

https://www./php-weizijiaocheng-377246.html

    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多