總算到了我們壓縮相關擴展的最后一篇文章了,最后我們要學習的也是 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
關注公眾號:【硬核專案經理】獲取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、專案管理學習資料
知乎、公眾號、抖音、頭條搜索【硬核專案經理】
B站ID:482780532
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/285580.html
標籤:PHP
上一篇:PHP的zip壓縮工具擴展包學習
下一篇:學習PDO中的錯誤與錯誤處理模式
