zoukankan      html  css  js  c++  java
  • Java 代码实现rar解压最全攻略操作

    最全Java 代码实现rar解压操作
    首先,非常感谢下面几位链接上的支持,之所以写这篇博文,主要在于总结,同时给第一次实现该功能的同学提供完整的参考。
    因为第一次遇到需要在代码中实现rar和zip的解压操作。而zip其实很简单,jdk自带的ZipUtil就可以实现,这里不做赘述。但是rar的解压,特别是5.0及其以上版本的解压,折腾了我很久。根据这几位博主的思路,结合起来最终实现了对rar文件的解压。
    unrar linux的安装:https://blog.51cto.com/lan2003/770497
    rar的软件解压方式 :http://www.xitongzhijia.net/xtjc/20150513/48197.html
    rar的第三方jar包解压方式:https://blog.csdn.net/fakergoing/article/details/82260699

    一、通过[com.github.junrar]实现winrar5.0以下版本解压
    1、首先贴出来maven依赖,这里使用的是最高版本4.0,但是依然无法解决5.0及其以上的版本问题。

    <!-- https://mvnrepository.com/artifact/com.github.junrar/junrar -->
    <dependency>
        <groupId>com.github.junrar</groupId>
        <artifactId>junrar</artifactId>
        <version>4.0.0</version>
    </dependency>

    2、代码实现:优化了https://blog.csdn.net/fakergoing/article/details/82260699中的linux中无法识别问题

    /**
         * 根据原始rar路径,解压到指定文件夹下
         * 这种方法只能解压rar 5.0版本以下的,5.0及其以上的无法解决
         *
         * @param srcRarPath       原始rar路径+name
         * @param dstDirectoryPath 解压到的文件夹
         */
        public static String unRarFile(String srcRarPath, String dstDirectoryPath) throws Exception {
            log.debug("unRarFile srcRarPath:{}, dstDirectoryPath:{}", srcRarPath, dstDirectoryPath);
            if (!srcRarPath.toLowerCase().endsWith(".rar")) {
                log.warn("srcFilePath is not rar file");
                return "";
            }
            File dstDiretory = new File(dstDirectoryPath);
            // 目标目录不存在时,创建该文件夹
            if (!dstDiretory.exists()) {
                dstDiretory.mkdirs();
            }
            // @Cleanup Archive archive = new Archive(new File(srcRarPath));  com.github.junrar 0.7版本jarAPI
            @Cleanup Archive archive = new Archive(new FileInputStream(new File(srcRarPath)));
            if (archive != null) {
                // 打印文件信息
                archive.getMainHeader().print();
                FileHeader fileHeader = archive.nextFileHeader();
                while (fileHeader != null) {
                    // 解决中文乱码问题【压缩文件中文乱码】
                    String fileName = fileHeader.getFileNameW().isEmpty() ? fileHeader.getFileNameString() : fileHeader.getFileNameW();
                    // 文件夹
                    if (fileHeader.isDirectory()) {
                        File fol = new File(dstDirectoryPath + File.separator + fileName.trim());
                        fol.mkdirs();
                    } else { // 文件
                        // 解决linux系统中分隔符无法识别问题
                        String[] fileParts = fileName.split("\\");
                        StringBuilder filePath = new StringBuilder();
                        for (String filePart : fileParts) {
                            filePath.append(filePart).append(File.separator);
                        }
                        fileName = filePath.substring(0, filePath.length() - 1);
                        File out = new File(dstDirectoryPath + File.separator + fileName.trim());
                        if (!out.exists()) {
                            // 相对路径可能多级,可能需要创建父目录.
                            if (!out.getParentFile().exists()) {
                                out.getParentFile().mkdirs();
                            }
                            out.createNewFile();
                        }
                        @Cleanup FileOutputStream os = new FileOutputStream(out);
                        archive.extractFile(fileHeader, os);
                    }
                    fileHeader = archive.nextFileHeader();
                }
            } else {
                log.warn("rar file decompression failed , archive is null");
            }
            return dstDirectoryPath;
        }

    3、该方法弊端

    最大的问题就在于无法实现winrar5.0及其以上版本的解压问题:WinRAR5之后,在rar格式的基础上,推出了另一种rar,叫RAR5,winrar官方并没有开源算法,jar包无法解析这种格式。
    咱们先看一段源码

    case MarkHeader:
        this.markHead = new MarkHeader(block);
        if (!this.markHead.isSignature()) {
            if (this.markHead.getVersion() == RARVersion.V5) {
                logger.warn("Support for rar version 5 is not yet implemented!");
                throw new RarException(RarExceptionType.unsupportedRarArchive);
            }
    
            throw new RarException(RarExceptionType.badRarArchive);
        }
    
        this.headers.add(this.markHead);
        break;

    这是junrar的主类Archive中的rar版本判断语句,这里明确说明了对于5.0版本尚未实现。并且抛出了RarException的异常。

    二、linux中安装unrar软件
    1、unrar安装包
    linux 32位:http://www.rarlab.com/rar/rarlinux-5.3.b4.tar.gz
    linux 64位:http://www.rarlab.com/rar/rarlinux-x64-5.3.b4.tar.gz
    由于是国外源,所以下载速度极慢,很可能下载不成功。

    还有一种最简单的安装方式【使用yum安装】:

    rpm -ivh http://mirrors.whsir.com/centos/whsir-release-centos.noarch.rpm

    yum install rar

    2、linux中安装unrar

    ①上传unrar到linux服务器 

    如 /usr 路径

    ②解压到指定路径:

    tar -zxf /usr/rarlinux-x64-5.7.1.tar.gz -C /usr/local/

    ③建立软连接:必须要有软连接,类似于jdk的环境变量,保证可以在任意目录下使用rar和unrar命令

    ln -s /usr/local/rar/rar /usr/local/bin/rar
    ln -s /usr/local/rar/unrar /usr/local/bin/unrar

    ④测试是否创建成功

    **在任意路径输入下列命令**
    rar
    unrar
    **出现如下信息表示安装成功**
    RAR 5.71   Copyright (c) 1993-2019 Alexander Roshal   28 Apr 2019
    Trial version             Type 'rar -?' for help

    3、Java中实现

    /**
    * 采用命令行方式解压文件
    * @param multipartFile 压缩文件
    * @param fileName 解压文件名称
    * @return
    */
    public RequestResult realExtractRar(MultipartFile multipartFile, String fileName) {
    RequestResult result = RequestResult.success();
    try {
    String filePath = zipPath + "test1/";

    File file = new File(zipPath);
    file.mkdirs();
    File fileDir = new File(filePath);
    fileDir.mkdirs();
    File saveFile = new File(fileDir, fileName);//将压缩包解析到指定位置
    multipartFile.transferTo(saveFile);
    // 获取windows中 WinRAR.exe的路径
    boolean bool = false;
    boolean isWin = System.getProperty("os.name").toLowerCase().contains("win");
    final boolean isLinux = System.getProperty("os.name").toLowerCase().indexOf("linux") >= 0;

    // 开始调用命令行解压,参数-o+是表示覆盖的意思
    String cmd ="";
    if(isWin) {
    cmd = winRarPath + " X -o+ " + saveFile + " " + filePath;
    }else if(isLinux){
    //如果linux做了软连接 不需要这里配置路径
    String cmdPath = "/usr/local/bin/unrar";
    cmd = "rar" + " X -o+ " + saveFile + " " + filePath;
    }
    Process proc = Runtime.getRuntime().exec(cmd);
    if (proc.waitFor() != 0) {
    if (proc.exitValue() == 0) {
    bool = false;
    }
    } else {
    bool = true;
    }
    System.out.println("解压" + (bool ? "成功" : "失败"));

    if (bool) {
    String filePath1 = filePath + fileName.substring(0, fileName.indexOf("."));
    result = getFiles(filePath1);
    }else{
    result = RequestResult.error("上传rar压缩包解压失败!");
    }
    }catch (Exception e) {
    e.printStackTrace();
    result = RequestResult.error("上传文件异常,异常原因:" + e.getMessage());
    }finally {
    //删除文件和文件压缩包
    FileUtils.DeleteFolder(zipPath);
    }

    return result;
    }

    /*
    * 通过递归得到某一路径下所有的目录及其文件
    */
    private RequestResult getFiles(String filePath) {
    RequestResult result = RequestResult.success();
    try {
    File srcfile = new File(filePath);
    File[] files = srcfile.listFiles();
    if (srcfile.exists()) {
    if (files.length == 0) {
    result = RequestResult.error("上传文件夹是空的!");
    } else {
    for (File pdffile : files) {
    if (pdffile.isDirectory()) {
    /*
    * 递归调用
    */
    getFiles(pdffile.getAbsolutePath());
    } else {
    String name = pdffile.getName();
    // File转MultipartFile
    FileInputStream input = new FileInputStream(pdffile);
    MultipartFile multipartFile1 = new MockMultipartFile("file", name, "text/plain", IOUtils.toByteArray(input));

    uploadDazlFromPdf(multipartFile1, name);

    input.close();
    }
    }
    }
    } else {
    result = RequestResult.error("上传文件解压失败!");
    }
    }catch (Exception e){
    e.printStackTrace();
    result = RequestResult.error("上传文件异常,异常原因:" + e.getMessage());
    }finally {
    //删除文件和文件压缩包
    FileUtils.DeleteFolder(zipPath);
    }
    return result;
    }

    4、关于Process proc = Runtime.getRuntime().exec(cmd);命令的补充说明

    // 需要指定参数一:命令位置;参数二:-c表示先执行第一个参数;参数三:你的命令。
    Runtime.getRuntime().exec(new String[]{"/bin/sh","c","xxx"});
    // 如果执行了上面第三步,可以任意目录使用rar和unrar命令,则可以省略第一和第二个参数,直接使用第三个参数

    5、关于unrar在linux中的命令说明

    #解压
    unrar x abc.rar 表示解压到同一个目录文件夹
    unrar e abc.rar 解压出来是散开的

    解压:rar x FileName.rar
    压缩:rar a FileName.rar DirName

    最后:此文章来源

    https://blog.csdn.net/weixin_42418785/article/details/90344053?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_utm_term~default-1.control&spm=1001.2101.3001.4242

    特此记录一遍后续使用方便

  • 相关阅读:
    Excel基础—文件菜单之创建保存
    Excel技巧—名称框的妙用
    Excel基础—文件菜单之设置信息
    Excel基础—文件菜单之打印共享账户
    Excel基础—文件菜单之设置选项
    Excel基础—工作界面概述
    linux环境下pathinfo 工作失败的改进函数
    javascript为网页元素绑定click事件
    将纯真ip数据库解析并导入mysql数据库中
    pgsql导入和导出数据
  • 原文地址:https://www.cnblogs.com/songyaru/p/15089194.html
Copyright © 2011-2022 走看看