关于php:PHP的rar解压读取扩展包学习

44次阅读

共计 4816 个字符,预计需要花费 13 分钟才能阅读完成。

作为压缩解压方面的扩大学习,两大王牌压缩格局 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; // 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;

句柄对象的 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) {//     ["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() 设置为 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.php

各自媒体平台均可搜寻【硬核项目经理】

正文完
 0