上一篇
java解压压缩rar文件怎么打开
- 后端开发
- 2025-08-13
- 39
Java原生不支持RAR,需借助第三方库(如
junrar),先导入相关JAR包,通过
Archive类加载RAR文件,遍历条目并提取到指定目录
在Java中处理RAR文件(解压与压缩)是一个常见需求,但由于Java标准库仅原生支持ZIP格式,因此需要借助第三方库或工具来实现RAR操作,以下是完整的技术方案解析,涵盖主流实现方式、代码示例、注意事项及常见问题解答。
核心挑战与解决方案概览
| 关键问题 | 原因分析 | 解决方案 |
|---|---|---|
| Java无原生RAR支持 | java.util.zip仅支持ZIP格式 |
使用第三方库(如junrar/JUNRAR) |
| 跨平台兼容性需求 | Windows/Linux/macOS差异 | 纯Java实现或封装系统命令 |
| 复杂功能缺失 | 分卷压缩、注释、恢复记录等 | 选择功能完善的第三方库 |
| 性能与资源占用 | JNI调用可能导致额外开销 | 权衡速度与内存管理 |
主流实现方案详解
方案1:基于junrar库(推荐)
特点:纯Java实现,无需安装外部程序,支持大多数RAR特性。
实施步骤:
-
添加Maven依赖:
<dependency> <groupId>com.github.junrar</groupId> <artifactId>junrar</artifactId> <version>0.7</version> <!-最新稳定版 --> </dependency> -
解压RAR文件代码示例:
import com.github.junrar.Archive; import com.github.junrar.exception.RarException; import com.github.junrar.rarfile.FileHeader; import java.io.File; import java.util.ArrayList; import java.util.List; public class RarExtractor { public static void extract(String sourcePath, String destDir) throws RarException, java.io.IOException { Archive archive = new Archive(new File(sourcePath)); File destDirFile = new File(destDir); if (!destDirFile.exists()) destDirFile.mkdirs(); List<FileHeader> fileHeaderList = archive.getFileHeaders(); for (FileHeader header : fileHeaderList) { File destFile = new File(destDir, header.getFileNameW()); archive.extractFile(header, destFile); } } } -
压缩生成RAR文件:

import com.github.junrar.rarfile.RarFile; import com.github.junrar.rarfile.RarOptions; import java.io.File; public class RarCreator { public static void create(String sourceDir, String destRar) throws Exception { RarFile rarFile = new RarFile(new File(destRar)); RarOptions options = new RarOptions(); options.setCreateSFX(false); // 不生成自解压文件 rarFile.create(new File(sourceDir), null, options); } }
优势:
纯Java实现,跨平台一致行为
支持密码保护(需扩展RarOptions)
可处理固实压缩、注释等元数据
对超大文件(>4GB)支持有限
不支持某些特殊RAR特性(如锁定档案)
方案2:调用系统级工具(WinRAR/7-Zip)
适用场景:需要极致性能或兼容特定工具链的场景。
Windows示例(通过ProcessBuilder):
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
public class SystemLevelExtractor {
public static void extractWithWinRAR(String rarPath, String outputDir) throws Exception {
ProcessBuilder pb = new ProcessBuilder(
"cmd.exe", "/c", ""C:\Program Files\WinRAR\WinRAR.exe"", "x", "-o+", outputDir, rarPath
);
pb.redirectErrorStream(true); // 合并错误流到标准输出
Process process = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line); // 可选:日志记录
}
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new RuntimeException("WinRAR extraction failed with code " + exitCode);
}
}
}
注意事项:
️ 强依赖目标系统环境配置
️ 存在安全风险(任意命令执行)
️ 不同平台的路径差异需特殊处理

方案3:Apache Commons Compress扩展
定位:轻量级补充方案,适合简单场景。
使用方法:
import org.apache.commons.compress.archivers.rar.RaArchiver;
import org.apache.commons.compress.archivers.rar.RaEntry;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class CommonsRarHandler {
// 解压示例
public static void decompress(File inputFile, File outputDir) throws IOException {
try (RaArchiver raArchiver = new RaArchiver()) {
raArchiver.setInputFile(inputFile);
raArchiver.extract(outputDir);
}
}
// 压缩示例
public static void compress(File inputFile, File outputFile) throws IOException {
try (RaArchiver raArchiver = new RaArchiver()) {
RaEntry entry = raArchiver.createRealEntry(inputFile, outputFile.getName());
raArchiver.putArchiveEntry(entry);
try (FileOutputStream fo = new FileOutputStream(outputFile)) {
raArchiver.buildArchive(fo);
}
}
}
}
局限性:
功能较junrar简化
更新频率较低(最后更新于2016年)
不支持新型压缩算法(如RAR5)
关键功能增强技巧
密码保护处理
// junrar库实现带密码解压
import com.github.junrar.Archive;
import com.github.junrar.exception.RarException;
import com.github.junrar.rarfile.FileHeader;
import java.io.File;
import java.util.List;
public class PasswordProtectedExtractor {
public static void extractWithPassword(String rarPath, String destDir, String password) throws RarException, IOException {
Archive archive = new Archive(new File(rarPath));
List<FileHeader> headers = archive.getFileHeaders();
for (FileHeader header : headers) {
if (header.isEncrypted()) {
header.setPassword(password.toCharArray()); // 设置解密密码
}
File outFile = new File(destDir, header.getFileNameW());
archive.extractFile(header, outFile);
}
}
}
进度监控实现
import com.github.junrar.Archive;
import com.github.junrar.exception.RarException;
import com.github.junrar.rarfile.FileHeader;
import java.io.File;
import java.util.List;
public class ProgressMonitor {
private long totalBytes = 0;
private long processedBytes = 0;
public void monitorExtraction(String rarPath, String destDir) throws RarException, IOException {
Archive archive = new Archive(new File(rarPath));
List<FileHeader> headers = archive.getFileHeaders();
for (FileHeader header : headers) {
totalBytes += header.getUnpackSize();
}
for (FileHeader header : headers) {
File outFile = new File(destDir, header.getFileNameW());
archive.extractFile(header, outFile);
processedBytes += header.getUnpackSize();
System.out.printf("Progress: %.2f%%%n", (processedBytes 100.0 / totalBytes));
}
}
}
异常处理最佳实践
try {
RarExtractor.extract("example.rar", "output");
} catch (RarException e) {
System.err.println("RAR格式错误: " + e.getMessage());
// 检查文件完整性或尝试修复档案
} catch (IOException e) {
System.err.println("IO异常: " + e.getMessage());
// 检查磁盘空间/文件权限
} catch (Exception e) {
System.err.println("未知错误: " + e.getMessage());
e.printStackTrace(); // 生产环境应替换为日志记录
}
性能对比与选型建议
| 指标 | junrar | System Tool | Commons Compress |
|---|---|---|---|
| 初始加载时间 | |||
| 单文件解压速度 | |||
| 多核利用率 | |||
| 内存消耗 | |||
| 跨平台稳定性 | |||
| 功能完整性 | |||
| 维护活跃度 | 高 | 中 | 低 |
推荐策略:
通用场景 → 优先选择junrar(平衡功能与便携性)
高性能需求 → 结合系统工具+异步处理(注意安全隔离)
轻量化需求 → Apache Commons Compress(仅限简单操作)

相关问答FAQs
Q1: 为什么有时解压出的中文文件名显示乱码?
A: 这是字符编码问题,RAR文件默认使用Windows的ANSI编码存储文件名,而Java使用UTF-8,解决方案:
- 强制指定编码(以junrar为例):
// 在提取前设置编码 Archive archive = new Archive(new File(rarPath)); archive.setCharset("GBK"); // 根据实际编码选择(GBK/GB2312/CP936) - 预处理文件名:在提取后统一转换编码。
- 推荐做法:创建RAR文件时统一使用UTF-8编码(需工具支持)。
Q2: 如何处理分卷压缩的RAR文件(part1.rar, r01.rar等)?
A: 当前主流Java库对分卷压缩支持有限,建议以下方案:
- 预处理合并:使用系统工具将分卷合并为单个RAR文件后再处理。
# Linux/macOS示例(使用unrar) unrar x part1.rar && touch done # 自动识别后续分卷
- 手动加载分卷:部分库支持指定分卷路径列表。
- 替代方案:改用ZIP格式进行分卷压缩(Java原生支持更好)。
