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

特此記錄一遍后續使用方便


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM