PHP實現(xiàn)rar解壓讀取擴展包小結(jié)
作為壓縮解壓方面的擴展學(xué)習(xí),兩大王牌壓縮格式 rar 和 zip 一直是計算機領(lǐng)域的壓縮終結(jié)者。rar 格式的壓縮包是 Windows 系統(tǒng)中有接近統(tǒng)治地位的存在,今天我們學(xué)習(xí)的 PHP 擴展就是針對于 rar 的壓縮包操作,不過,PHP 的 rar 擴展僅能讀取和解壓 rar 格式的壓縮包,并不能進行壓縮操作。
php-rar 擴展在 pecl 的安裝包已經(jīng)過時了,無法在 PHP7 中使用,我們需要使用它在 github 上的源碼進行編譯安裝才能夠在 PHP7 的環(huán)境下安裝成功。
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 擴展有兩種形式的寫法,一種是面向?qū)ο蟮模簿褪鞘褂?RarArchive 類來操作壓縮包。另一種方式就是直接使用一個函數(shù) rar_open 用來獲取一個 rar 文件的句柄。它們都重寫了 __toString 方法,所以我們可以直接打印句柄的內(nèi)容看到當(dāng)前句柄所操作的具體文件。
當(dāng)我們關(guān)閉句柄時,句柄對象依然能夠進行輸出,但后面會顯示一個 closed 。這時的句柄對象已經(jīng)不能進行其它操作了。
$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 對象的一些方法可以幫我們獲取當(dāng)前壓縮包的信息。比如 getComment() 獲取壓縮包的說明信息,isBroken() 獲取當(dāng)前壓縮包是否有損壞,isSolid() 檢查當(dāng)前壓縮包是否可用。而 setAllowBroken() 方法是讓我們允許對損壞的壓縮包進行操作。這里我們給出了面向?qū)ο蠛兔嫦蜻^程的寫法。
壓縮包內(nèi)的每個實體文件或目錄操作 RarEntry
獲得壓縮包的句柄之后,我們就需要更進一步地獲取壓縮包內(nèi)部的內(nèi)容。而句柄對象中就已經(jīng)保存了壓縮包內(nèi)部的各個文件和目錄的對象 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; // ldxlcs/ldxlcs/game.htm echo $gameEntry->getUnpackedSize(), PHP_EOL; // 56063 $fp = $gameEntryNo->getStream(); while (!feof($fp)) { $buff = fread($fp, 8192); if ($buff !== false) { echo $buff; } else { break; } //fread error } // 輸出文件的全部內(nèi)容 echo PHP_EOL; echo 'Entry extract: ', $gameEntry->extract("./"), PHP_EOL;
句柄對象的 getEntry() 方法就是用于獲取指定的文件或者目錄內(nèi)容的。它獲取的是單個文件或目錄,所以必須明確地指定需要獲取的文件內(nèi)容。通過這個方法,我們可以拿到一個 RarEntry 對象。接下來,就是這個對象的一些操作。
RarEntry 對象的 getName() 方法用于獲取文件名稱,這個文件名稱是帶路徑的,這個路徑是壓縮包內(nèi)的絕對路徑。getUnpackedSize() 方法用于獲取文件的大小,getStream() 用于獲取文件流,通過 getStream() 方法,我們就可以直接打印輸出文件的內(nèi)容。
當(dāng)然,最最重要的是,我們可以通過 extract() 方法來直接解壓一個文件到指定的目錄。php-rar 擴展并沒有提供一個能夠完全地解壓整個壓縮包的方法,所以如果我們需要對整個壓縮包進行解壓的話,就需要通過循環(huán)遍歷壓縮包內(nèi)部的全部內(nèi)容來對這些文件一個一個地進行解壓。
最后,我們就來看看如何遍歷壓縮包內(nèi)的全部內(nèi)容。
$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; } // 壓縮包中所有文件的內(nèi)容 // 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 對象的數(shù)組,里面包含的就是這個 rar 壓縮包里面的全部內(nèi)容。在這段代碼中,我們還打印了 RarEntry 對象的其它一些屬性方法,根據(jù)名稱也能大概了解這些方法都是獲取關(guān)于文件的各種信息的,大家可以自行測試。
異常處理
最后,如果打開錯了文件或者獲取壓縮包內(nèi)部沒有的文件時,php-rar 擴展會以 PHP 錯誤的形式報錯。但既然提供了完整的面向?qū)ο髮懛?,那么它也必然提供了一套面向?qū)ο蟮漠惓L幚頇C制。
// 不打開 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) { // ["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":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() 設(shè)置為 true ,就能夠開啟 php-rar 擴展的異常處理機制,這時,我們打開一個錯誤的文件,或者去獲取壓縮包內(nèi)的一個錯誤文件路徑,那么,錯誤信息就會以異常的形式進行拋出。
總結(jié)
這套擴展是不是感覺很人性化?即提供了面向?qū)ο蟮姆绞剑蔡峁┝艘院瘮?shù)操作為主的面向過程的方式。但是,這樣做其實并沒有太多的好處,因為又要兼顧老代碼,又要兼顧新思想,本身擴展的內(nèi)部實現(xiàn)相必也會復(fù)雜很多。我們自己寫代碼的時候就盡量不要這么寫了,在重構(gòu)的時候一步步的向最新的形式遷移即可。
關(guān)于 rar 的壓縮操作并沒有找到太多有用的資料。當(dāng)然,我們在生產(chǎn)環(huán)境中如果要生成壓縮包的話大部分情況下都會直接去生成 zip 格式的提供給用戶,畢竟大部分的客戶端軟件都是能夠同時支持 rar 和 zip 格式文件的解壓的,如果一定要指定生成 rar 的話,也可以多多和產(chǎn)品經(jīng)理或者客戶商量。有的時候,技術(shù)的難點是可以通過業(yè)務(wù)的變通來解決的,最重要的其實還是在于溝通。
測試代碼:
參考文檔:
https://www.php.net/manual/zh/book.rar.php
以上就是PHP的rar解壓讀取擴展包學(xué)習(xí)的詳細(xì)內(nèi)容,更多關(guān)于PHP rar解壓讀取的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
以PHP代碼為實例詳解RabbitMQ消息隊列中間件的6種模式
這篇文章主要介紹了以PHP代碼為實例詳解RabbitMQ消息隊列中間件的6種模式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05Yii2.0小部件GridView(兩表聯(lián)查/搜索/分頁)功能的實現(xiàn)代碼
這篇文章主要介紹了Yii2.0小部件GridView(兩表聯(lián)查/搜索/分頁)功能的實現(xiàn)代碼,需要的朋友可以參考下2017-08-08laravel 5 實現(xiàn)模板主題功能(續(xù))
前面一篇文章,我們簡單討論了laravel模板主題功能,本文我們繼續(xù)探討laravel模板主題功能的實現(xiàn),本次實現(xiàn)比較重,有興趣慢慢看吧。2015-03-03PHP中將網(wǎng)頁導(dǎo)出為Word文檔的代碼
今天要探討的是PHP網(wǎng)頁導(dǎo)出Word文檔的方法,使用其他語言的朋友也可以參考,因為原理是差不多的2012-05-05把1316這個數(shù)表示成兩個數(shù)的和,其中一個為13的倍數(shù),另一個是11的倍數(shù),求這兩個數(shù)。
把1316這個數(shù)表示成兩個數(shù)的和,其中一個為13的倍數(shù),另一個是11的倍數(shù),求這兩個數(shù)。2011-06-06php中simplexml_load_string使用實例分享
這篇文章主要介紹了php中simplexml_load_string使用實例,需要的朋友可以參考下2014-02-02PHP+MySQL投票系統(tǒng)的設(shè)計和實現(xiàn)分享
php投票系統(tǒng)的設(shè)計和實現(xiàn),需要的朋友可以參考下代碼與數(shù)據(jù)庫結(jié)果設(shè)計,最后腳本之家提供了源碼下載2012-09-09