最全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
特此記錄一遍后續使用方便