As an extended study in compression and decompression, the two ace compression formats rar and zip have always been the most popular in the computer field. compression terminator. The rar format compressed package is close to dominating in Windows systems. The PHP extension we are learning today is for rar compressed package operations. However, PHP's rar extension can only read and decompress rar format compressed packages, and Compression operations cannot be performed.
php-rar The installation package of the pecl extension is outdated and cannot be used in PHP7. We need to use its source code on github to compile and install it in order to install it successfully in the PHP7 environment.
https://github.com/cataphract/php-rar
After git clone directly, you can install it in the normal way of PHP extension.
Get the compressed package handle 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 extension has two forms of writing, one is object-oriented, that is, using the RarArchive class to operate the compressed package. Another way is to directly use a function rar_open to obtain the handle of a rar file. They all override the __toString method, so we can directly print the contents of the handle to see the specific file operated by the current handle.
When we close the handle, the handle object can still output, but a closed will be displayed later. The handle object at this time can no longer perform other operations.
$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;
Some methods of the RarArchive object can help us obtain information about the current compressed package. For example, getComment() obtains the description information of the compressed package, isBroken() obtains whether the current compressed package is damaged, and isSolid() checks whether the current compressed package is available. The setAllowBroken() method allows us to operate on damaged compressed packages. Here we give object-oriented and process-oriented writing methods.
Each entity file or directory in the compressed package operates RarEntry
After obtaining the handle of the compressed package, we need to further obtain the contents inside the compressed package. The handle object has already saved the objects RarEntry of each file and directory inside the compressed package.
$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 } // 输出文件的全部内容 echo PHP_EOL; echo 'Entry extract: ', $gameEntry->extract("./"), PHP_EOL;
The getEntry() method of the handle object is used to obtain the contents of the specified file or directory. It obtains a single file or directory, so the content of the file to be obtained must be explicitly specified. Through this method, we can get a RarEntry object. Next, there are some operations on this object.
The getName() method of the RarEntry object is used to obtain the file name. This file name has a path, and this path is the absolute path within the compressed package. The getUnpackedSize() method is used to get the size of the file, and getStream() is used to get the file stream. Through the getStream() method, we can directly print the contents of the file.
Of course, the most important thing is that we can directly extract a file to the specified directory through the extract() method. The php-rar extension does not provide a method that can completely decompress the entire compressed package, so if we need to decompress the entire compressed package, we need to decompress these files one by one by looping through the entire contents of the compressed package. .
Finally, let’s take a look at how to traverse all the contents of the compressed package.
$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; }
We directly use the getEntries() method of the RarArchive object. Through this method, we can obtain an array of RarEntry objects, which contains all the contents of the rar compressed package. In this code, we also printed some other attribute methods of the RarEntry object. Based on the names, you can roughly understand that these methods are used to obtain various information about the file. You can test them yourself.
Exception handling
Finally, if you open the wrong file or obtain a file that is not inside the compressed package, the php-rar extension will report an error in the form of a PHP error. But since it provides a complete object-oriented writing method, it must also provide a set of object-oriented exception handling mechanisms.
// 不打开 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 // } }
As long as RarException::setUsingExceptions() is set to true, the exception handling mechanism of the php-rar extension can be enabled. At this time, we open an error file or obtain an error in the compressed package. file path, then the error message will be thrown in the form of an exception.
Summary
Does this set of extensions feel very user-friendly? That is, it provides an object-oriented approach and a process-oriented approach focusing on functional operations. However, there are actually not many benefits to doing this, because you have to take into account both old code and new ideas, and the internal implementation of the extension itself will be much more complicated. We try not to write like this when we write our own code, and just migrate to the latest form step by step when refactoring.
关于 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
推荐:《PHP视频教程》