PHP實現rar解壓讀取擴充套件包小結
作為壓縮解壓方面的擴充套件學習,兩大王牌壓縮格式 rar 和 zip 一直是計算機領域的壓縮終結者。rar 格式的壓縮包是 Windows 系統中有接近統治地位的存在,今天我們學習的 php 擴充套件就是針對於 rar 的壓縮包操作,不過,PHP 的 rar 擴充套件僅能讀取和解壓 rar 格式的壓縮包,並不能進行壓縮操作。
php-rar 擴充套件在 pecl 的安裝包已經過時了,無法在 PHP7 中使用,我們需要使用它在 github 上的原始碼進行編譯安裝才能夠在 PHP7 的環境下安裝成功。
https://github.com/cataphract/php-rar
直接 git clone 之後就可以按正常的 PHP 擴充套件的方式進行安裝。
獲取壓縮包控制代碼 RarArchive
$arch = RarArchive::open("test.rar"); $archNo = rar_open("test.rar"); echo $arch,PHP_EOL; // RAR Archive "/data/www/blog/test.rar" echo $archNo,PHP_EOL; // RAR Archive "/data/www/blog/test.rar" $arch->close(); rar_close($archNo); echo $arch,PHP_EOL; // RAR Archive "/data/www/blog/test.rar" (closed) echo $archNo,PHP_EOL; // RAR Archive "/data/www/blog/test.rar" (closed)
php-rar 擴充套件有兩種形式的寫法,一種是面向物件的,也就是使用 RarArchive 類來操作壓縮包。另一種方式就是直接使用一個函式 rar_open 用來獲取一個 rar 檔案的控制代碼。它們都重寫了 __toString 方法,所以我們可以直接列印控制代碼的內容看到當前控制代碼所操作的具體檔案。
當我們關閉控制代碼時,控制代碼物件依然能夠進行輸出,但後面會顯示一個 closed 。這時的控制代碼物件已經不能進行其它操作了程式設計客棧。
$arch = RarArchive::open("test.rar"); $archNo = rar_open("test.rar"); echo $arch->getComment(),PHP_EOL; echo $arch->isBroken(),PHP_EOL; echo $arch->isSolid(),PHP_EOL; echo rar_comment_get($archNo),PHP_EOL; echo rar_broken_is($archNo),PHP_EOL; echo rar_solid_is($archNo),PHP_EOL; echo $arch->setAllowBroken(true),PHP_EOL; echo rar_allow_broken_set($archNo,true),PHP_EOL;
RarArchive 物件的一些方法可以幫我們獲取當前壓縮包的資訊。比如 getComment() 獲取壓縮包的說明資訊,isBroken() 獲取當前壓縮包是否有損壞,isSolid() 檢查當前壓縮包是否可用。而 setAllowBroken() 方法是讓我們允許對損壞的壓縮包進行操作。這裡我們給出了面向物件和麵向過程的寫法。
壓縮包內的每個實體檔案或目錄操作 RarEntry
獲得壓縮包的控制代碼之後,我們就需要更進一步地獲取壓縮包內部的內容。而控制代碼物件中就已經儲存了壓縮包內部的各個檔案和目錄的物件 RarEntry 。
$gameEntry = $arch->getEntry('ldxlcs/ldxlcs/game.htm'); echo $gameEntry->getName(),PHP_EOL; // ldxlcs/ldxlcs/game.htm echo $gameEntry->getUnpackedSize(),PHP_EOL; // 56063 $gameEntryNo = rar_entry_get($arch,"ldxlcs/ldxlcs/game.htm"); echo $gameEntry->getName(),PHP_EOL; // 56063 $fp = $gameEntryNo->getStream(); while (!feof($fp)) { $buff = fread($fp,8192); if ($buff !== false) { echo $buff; } else { break; } //fread error } // 輸出檔案的全部內容 echo PHP_EOL; echo 'Entry extract: ',$gameEntry->extract("./"),PHP_EOL;
控制代碼物件的 getEntry() 方法就是用於獲取指定的檔案或者目錄內容的。它獲取的是單個檔案或目錄,所以必須明確地指定需要獲取的檔案內容。通過這個方法,我們可以拿到一個 RarEntry 物件。接下來,就是這個物件的一些操作。
RarEntry 物件的 getName() 方法用於獲取檔名稱,這個檔名稱是帶路徑的,這個路徑是壓縮包內的絕對路徑。getUnpackedSize() 方法用於獲取檔案的大小,getStream() 用於獲取檔案流,通過 getStream() 方法,我們就可以直接列印輸出程式設計客棧檔案的內容。
當然,最最重要的是,我們可以通過 extract() 方法來直接解壓一個檔案到指定的目錄。php-rar 擴充套件並沒有提供一個能夠完全地解壓整個壓縮包的方法,所以如果我們需要對整個壓縮包進行解壓的話,就需要通過迴圈遍歷壓縮包內部的全部內容來對這些檔案一個一個地進行解壓。
最後,我們就來看看如何遍歷壓縮包內的全部內容。
$entries = $arch->getEntries(); foreach ($entries as $en) { echo $en,PHP_EOL; echo $en->getName(),PHP_EOL; echo $en->getUnpackedSize(),PHP_EOL; echo $en->getAttr(),PHP_EOL; echo $en->getCrc(),PHP_EOL; echo $en->getFileTime(),PHP_EOL; echo $en->getHostOs(),PHP_EOL; echo $en->getMethod(),PHP_EOL; echo $en->getPackedSize(),PHP_EOL; echo $en->getVersion(),PHP_EOL; echo $en->isDirectory(),PHP_EOL; echo $en->isEncrypted(),PHP_EOL; } // 壓縮包中所有檔案的內容 // RarEntry for file "ldxlcs/ldxlcs/game.htm" (3c19abf6) // ldxlcs/ldxlcs/game.htm // 56063 // 32 // 3c19abf6 // 2017-09-10 13:25:04 // 2 // 51 // 7049 // 200 // …… $entriesNo = rar_list($archNo); foreach ($entriesNo as $en) { echo $en->getName(),PHP_EOL; }
直接使用的是 RarArchive 物件的 getEntries() 方法,我們通過這個方法可以獲得一個 RarEntry 物件的陣列,裡面包含的就是這個 rar 壓縮包裡面的全部內容。在這段程式碼中,我們還列印了 RarEntry 物件的其它一些屬性方法,根據名稱也能大概瞭解這些方法都是獲取關於檔案的各種資訊的,大家可以自行測試。
異常處理
最後,如果開啟錯了檔案或者獲取壓縮包內部沒有的檔案時,php-rar 擴充套件會以 PHP 錯誤的形式報錯。但既然提供了完整的面向物件寫法,那麼它也必然提供了一套面向物件的異常處理機制。
// 不開啟 UsingExceptions 全部錯誤會走 PHP 錯誤機制,開啟後走 PHP 的異常機制
RarException::setUsingExceptions(true);
var_dump(RarException::isUsingExceptions()); // bool(true)
try {
$arch = RarArchive::open("test1.rar");
$arch->getEntry('ttt.txt');
} catch (RarException $e) {
var_dump($e);
// object(RarException)#35 (7) {
// http://www.cppcns.com ["message":protected]=>
// string(91) "unRAR internal error: Failed to open /data/www/blog/test1.rar: ERAR_EOPEN (file open error)"
// ["string":"Exception":private]=>
// string(0) ""
// ["code":protected]=>
// int(15)
// ["file":protected]=>
// string(22) "/data/www/blog/rar.php"
// ["line"http://www.cppcns.com:protected]=>
// int(93)
// ["trace":"Exception":private]=>
// array(1) {
// [0]=>
// array(6) {
// ["file"]=>
// string(22) "/data/www/blog/rar.php"
// ["line"]=>
// int(93)
// ["function"]=>
// string(4) "open"
// ["class"]=>
// string(10) "RarArchive"
// ["type"]=>
// string(2) "::"
// ["args"]=>
// array(1) {
// [0]=>
// string(9) "test1.rar"
// }
// }
// }
// ["previous":"Exception":private]=>
// NULL
// }
}
只要將 RarException::setUsingExceptions() 設定為 true ,就能夠開啟 php-rar 擴充套件的異常處理機制,這時,我們開啟一個錯誤的檔案,或者去獲取壓縮包內的一個錯誤檔案路徑,那麼,錯誤資訊就會以異常的形式進行丟擲。
總結
這套擴充套件是不是感覺很人性化?即提供了面向物件的方式,也提供了以函式操作為主的面向過程的方式。但是,這樣做其實並沒有太多的好處,因為又要兼顧老程式碼,又要兼顧新思想,本身擴充套件的內部實現相必也會複雜很多。我們自己寫程式碼的時候就儘量不要這麼寫了,在重構的時候一步步的向最新的形式遷移即可。
關於 rar 的壓縮操作並沒有找到太多有用的資料。當然,我們在生產環境中如果要生成壓縮包的話大部分情況下都會直接去生成 zip 格式的提供給使用者,畢竟大部分的客戶端軟體都是能夠同時支援 rar 和 zip 格式檔案的解壓的,如果一定要指定生成 rar 的話,也可以多多和產品經理或者客戶商量。有的時候,技術的難點是可以通過業務的變通來解決的,最重要的其實還是在於溝通。
測試程式碼:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202007/source/PHP%E7%9A%84rar%E8%A7%A3%E5%8E%8B%E8%AF%BB%E5%8F%96%E6%89%A9%E5%B1%95%E5%8C%85%E5%AD%A6%E4%B9%A0.php
參考文件:
https://www.php.net/manual/zh/book.rar.pwww.cppcns.comhp
以上就是PHP的rar解壓讀取擴充套件包學習的詳細內容,更多關於PHP rar解壓讀取的資料請關注我們其它相關文章!