使用java-unrar库,对rar压缩包内的压缩包、目录和文件进行循环遍历,文件名包含中文
时间: 2025-08-02 18:30:12 浏览: 2
<think>我们使用java-unrar库来解压RAR文件,并且需要处理中文文件名。首先,我们需要添加java-unrar的依赖。如果使用Maven,可以添加以下依赖:```xml<dependency><groupId>com.github.axet</groupId><artifactId>java-unrar</artifactId><version>1.7.0-7</version></dependency>```然后,我们将编写一个程序来遍历RAR压缩包内的所有条目(包括嵌套的压缩包、目录和文件)。注意,由于RAR文件可能包含嵌套的压缩包,我们需要递归处理。但是,java-unrar库只支持RAR格式,所以如果嵌套了其他格式的压缩包,可能需要其他库。这里我们假设只处理RAR嵌套。另外,中文文件名的问题,我们需要确保正确设置编码。java-unrar库默认使用平台编码,但RAR文件可能是用其他编码(如UTF-8)创建的。我们可以通过设置`Archive`的编码来解决。以下是一个示例代码,它递归地遍历RAR文件中的所有条目,并处理中文文件名:```javaimportde.innosystec.unrar.Archive;importde.innosystec.unrar.exception.RarException;importde.innosystec.unrar.rarfile.FileHeader;importjava.io.File;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.OutputStream;importjava.nio.charset.StandardCharsets;importjava.util.List;publicclassUnrarExample{publicstaticvoidmain(String[]args){StringrarFilePath="path/to/your/file.rar";StringoutputDir="path/to/output/directory";try{extractRar(rarFilePath,outputDir);}catch(RarException|IOExceptione){e.printStackTrace();}}publicstaticvoidextractRar(StringrarFilePath,StringoutputDir)throwsRarException,IOException{FilerarFile=newFile(rarFilePath);FileoutputDirFile=newFile(outputDir);if(!outputDirFile.exists()){outputDirFile.mkdirs();}//设置编码为UTF-8,以支持中文Archivearchive=newArchive(rarFile,null,StandardCharsets.UTF_8);try{List<FileHeader>headers=archive.getFileHeaders();for(FileHeaderheader:headers){StringfileName=header.getFileNameString().trim();//如果是目录,创建目录FileoutFile=newFile(outputDir,fileName);if(header.isDirectory()){outFile.mkdirs();}else{//如果是文件,确保父目录存在Fileparent=outFile.getParentFile();if(parent!=null&&!parent.exists()){parent.mkdirs();}//提取文件try(OutputStreamos=newFileOutputStream(outFile)){archive.extractFile(header,os);}}//如果该文件是RAR压缩包,递归解压if(fileName.toLowerCase().endsWith(".rar")){extractRar(outFile.getAbsolutePath(),outFile.getParent()+File.separator+"extracted");}}}finally{archive.close();}}}```解释:1.我们使用`Archive`类打开RAR文件,并指定使用UTF-8编码,这样可以正确处理中文文件名。2.遍历RAR文件中的每个`FileHeader`,它代表一个条目(文件或目录)。3.对于目录,我们创建对应的目录。4.对于文件,我们创建文件并写入内容。同时,如果文件名以`.rar`结尾(不区分大小写),则递归调用`extractRar`方法进行解压。5.注意:递归解压时,我们将嵌套的RAR文件解压到其所在目录下的"extracted"子目录中,避免覆盖原有文件。你可以根据需要修改。注意:递归解压可能会遇到无限循环或者压缩包过深的问题,实际应用中可能需要设置递归深度限制或者避免解压某些特定文件。另外,如果RAR文件有密码,我们还需要处理密码。上述代码中没有处理密码,如果需要,可以在`Archive`构造时传入密码。§§相关问题§§:1.如何处理RAR文件的密码保护?2.如果嵌套的压缩包不是RAR格式(例如ZIP),该如何处理?3.如何避免递归解压时可能出现的无限循环(比如自包含的RAR文件)?4.除了UTF-8,还有哪些常见的编码需要处理?</think>### 使用 java-unrar 处理含中文文件名的 RAR 压缩包
以下是完整的解决方案,使用 `java-unrar` 库遍历 RAR 压缩包内的所有内容(包括嵌套压缩包、目录和文件),并正确处理中文文件名:
#### 解决方案代码
```java
import de.innosystec.unrar.Archive;
import de.innosystec.unrar.exception.RarException;
import de.innosystec.unrar.rarfile.FileHeader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class ChineseRarExtractor {
// 递归遍历 RAR 文件内容
public static void traverseRar(String rarPath, String outputDir, Charset charset)
throws RarException, IOException {
File rarFile = new File(rarPath);
File outDir = new File(outputDir);
if (!outDir.exists()) outDir.mkdirs();
try (Archive archive = new Archive(rarFile, null, charset)) {
List<FileHeader> headers = archive.getFileHeaders();
for (FileHeader header : headers) {
// 处理中文文件名
String fileName = fixChineseFileName(header.getFileNameString(), charset);
File outputFile = new File(outDir, fileName);
if (header.isDirectory()) {
// 创建目录
outputFile.mkdirs();
System.out.println("创建目录: " + outputFile.getAbsolutePath());
} else {
// 确保父目录存在
outputFile.getParentFile().mkdirs();
// 提取文件
try (OutputStream os = new FileOutputStream(outputFile)) {
archive.extractFile(header, os);
}
System.out.println("提取文件: " + outputFile.getAbsolutePath());
// 递归处理嵌套 RAR
if (fileName.toLowerCase().endsWith(".rar")) {
String nestedDir = outputFile.getParent() + File.separator + "extracted_" +
fileName.substring(0, fileName.lastIndexOf('.'));
traverseRar(outputFile.getAbsolutePath(), nestedDir, charset);
}
}
}
}
}
// 修复中文文件名编码问题
private static String fixChineseFileName(String original, Charset charset) {
// 如果原始字节已经是正确编码,直接返回
if (charset.newEncoder().canEncode(original)) {
return original;
}
// 尝试重新解析文件名字节
try {
byte[] nameBytes = original.getBytes("ISO-8859-1");
return new String(nameBytes, charset);
} catch (Exception e) {
return original; // 回退到原始名称
}
}
public static void main(String[] args) {
String rarPath = "path/to/your/archive.rar";
String outputDir = "path/to/output/directory";
try {
// 使用 UTF-8 编码处理中文
traverseRar(rarPath, outputDir, StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
### 代码解释
1. **核心组件**:
- `Archive`:java-unrar 的主类,用于打开 RAR 文件
- `FileHeader`:表示 RAR 内的文件/目录条目
2. **中文处理关键点**:
- **编码指定**:在 `Archive` 构造函数中显式设置 `StandardCharsets.UTF_8`
- **文件名修复**:
```java
private static String fixChineseFileName(String original, Charset charset) {
// 转换 ISO-8859-1 字节序列到指定编码
byte[] nameBytes = original.getBytes("ISO-8859-1");
return new String(nameBytes, charset);
}
```
这是因为 java-unrar 内部可能返回 ISO-8859-1 编码的字符串,需要重新解析为正确编码
3. **递归处理流程**:
```java
if (fileName.toLowerCase().endsWith(".rar")) {
String nestedDir = outputFile.getParent() + File.separator + "extracted_" +
fileName.substring(0, fileName.lastIndexOf('.'));
traverseRar(outputFile.getAbsolutePath(), nestedDir, charset);
}
```
- 检测嵌套 RAR 文件
- 在新目录中递归解压(避免覆盖)
4. **目录结构处理**:
- 使用 `header.isDirectory()` 检测目录条目
- 自动创建缺失的父目录:`outputFile.getParentFile().mkdirs()`
### 依赖配置(Maven)
```xml
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>java-unrar</artifactId>
<version>1.7.0-7</version>
</dependency>
```
### 注意事项
1. **编码选择**:
- 优先使用 `UTF-8`(`StandardCharsets.UTF_8`)
- 对于旧版 WinRAR 创建的文件,可尝试 `GBK` 或 `GB2312`
```java
Charset.forName("GBK"); // 替代 UTF-8
```
2. **嵌套压缩包限制**:
- 仅自动处理嵌套的 RAR 文件
- 如需处理 ZIP/7z 等格式,需添加额外逻辑
3. **异常处理**:
- 捕获 `RarException` 和 `IOException`
- 密码保护文件需要额外处理(未包含在本示例中)
4. **路径安全**:
- 使用 `File.separator` 保证跨平台兼容性
- 过滤特殊字符(如 `..`)防止路径遍历攻击
阅读全文
相关推荐




















