作为压缩解压的延伸学习,rar和zip这两个王牌压缩格式一直是计算机领域压缩的终结者。rar格式的压缩包在Windows系统中几乎占据了主导地位。我们今天学习的PHP扩展是针对rar的压缩包操作的。但是PHP的rar扩展只能读取并解压rar格式的压缩包,而不能进行压缩操作。php-rar扩展的pecl安装包已经过时,无法在PHP7中使用。我们需要在github上使用它的源码编译安装才能在PHP7环境下安装成功。https://github.com/cataphhract/php-rar直接gitclone后可以正常安装PHP扩展。获取存档句柄RarArchive$arch=RarArchive::open("test.rar");$archNo=rar_open("test.rar");echo$arch,PHP_EOL;//RAR存档"/data/www/blog/test.rar"echo$archNo,PHP_EOL;//RAR存档"/data/www/blog/test.rar"$arch->close();rar_close($archNo);echo$arch,PHP_EOL;//RAR存档“/data/www/blog/test.rar”(关闭)echo$archNo,PHP_EOL;//RARArchive"/data/www/blog/test.rar"(closed)php-rar扩展有两种写法,一种是面向对象的,即使用RarArchive类来操作压缩包。另一种方法是直接使用函数rar_open来获取rar文件的句柄。它们都重写了__toString方法,这样我们就可以直接打印句柄的内容来查看当前句柄操作的具体文件。当我们关闭句柄的时候,句柄对象仍然可以输出,只是后面会显示一个closed。这时候句柄对象就不能再进行其他操作了。$arch=RarArchive::open("test.rar");$archNo=rar_open("test.rar");回声$arch->getComment(),PHP_EOL;echo$arch->isBroken(),PHP_EOL;echo$arch->isSolid(),PHP_EOL;echorar_comment_get($archNo),PHP_EOL;echorar_broken_is($archNo),PHP_EOL;echorar_solid_is($archNo),PHP_EOL;echo$arch->setAllowBroken(true),PHP_EOL;回声rar_allow_broken_set($archNo,true),PHP_EOL;RarArchive对象的一些方法可以帮助我们获取当前存档的信息。比如getComment()获取压缩包的描述信息,isBroken()获取当前压缩包是否损坏,isSolid()检测当前压缩包是否可用。而setAllowBroken()方法就是让我们可以对损坏的压缩包进行操作。这里我们给出面向对象和面向过程的写法。压缩包中的各个实体文件或目录操作RarEntry获取压缩包句柄后,我们需要进一步获取压缩包里面的内容。handle对象中保存了压缩包内每个文件和目录的RarEntry对象。$gameEntry=$arch->getEntry('ldxlcs/ldxlcs/game.htm');echo$gameEntry->getName(),PHP_EOL;//ldxlcs/ldxlcs/game.htmecho$gameEntry->getUnpackedSize(),PHP_EOL;//56063$gameEntryNo=rar_entry_get($arch,"ldxlcs/ldxlcs/game.htm");echo$gameEntry->getName(),PHP_EOL;//ldxlcs/ldxlcs/game.htmecho$gameEntry->getUnpackedSize(),PHP_EOL;//56063$fp=$gameEntryNo->getStream();while(!feof($fp)){$buff=fread($fp,8192);如果($buff!==false){echo$buff;}else{休息;}//freaderror}//输出文件的全部内容echoPHP_EOL;echo'条目提取:',$gameEntry->extract("./"),PHP_EOL;句柄对象的getEntry()方法用于获取指定文件或目录的内容。它获取单个文件或目录,因此必须明确指定要获取的文件的内容。通过这个方法,我们可以得到一个RarEntry对象。接下来就是对这个对象的一些操作。RarEntry对象的getName()方法用于获取文件名,文件名有路径,路径为压缩包中的绝对路径。getUnpackedSize()方法用于获取文件大小,getStream()方法用于获取文件流。通过getStream()方法,我们可以直接打印出文件的内容。当然,最重要的是我们可以直接通过extract()方法将一个文件解压到指定目录。php-rar扩展没有提供完整解压整个压缩包的方法,所以如果我们需要解压整个压缩包,就需要通过循环遍历压缩包的全部内容,将这些文件一个一个解压。最后我们来看看如何遍历压缩包的所有内容。$entries=$arch->getEntries();foreach($entriesas$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$zh->getPackedSize(),PHP_EOL;echo$zh->getVersion(),PHP_EOL;echo$en->isDirectory(),PHP_EOL;echo$en->isEncrypted(),PHP_EOL;}//压缩包内所有文件内容56063//32//3c19abf6//2017-09-1013:25:04//2//51//7049//200//......$entriesNo=rar_list($archNo);foreach($entriesNoas$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内部错误:无法打开/data/www/blog/test1.rar:ERAR_EOPEN(文件打开错误)"//["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"]=>//数组(1){//[0]=>//字符串(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各媒体平台均可搜索【硬核项目经理】
