在Java开发中,处理压缩文件(如ZIP、RAR等)是一项常见的任务,特别是在需要处理大量数据、备份或分发应用程序时。Java标准库(Java SE)提供了对ZIP格式的原生支持,通过java.util.zip
包中的类来实现压缩和解压功能。本文将重点介绍如何使用Java来解压ZIP或RAR压缩包。
一、解压压缩包
解压压缩包,借助ZipInputStream类,可以读取到压缩包中的每一个文件,然后根据读取到的文件属性,写入到相应路径下即可。对于解压压缩包中是文件树的结构,每读取到一个文件后,如果是多层路径下的文件,需要先创建父目录,再写入文件流。
1.zip解压代码实现:
// 解压zip格式
public static void unzip(String path){
// 根据原始路径(字符串),创建源文件(File对象)
File sourceFile = new File(path);
// 根目录
String sourceFileName = sourceFile.getName();
File rootDir = new File(sourceFile.getParent()+"\\"+sourceFileName.substring(0,sourceFileName.lastIndexOf(".")));
// 判断根目录是否已经存在
if(rootDir.exists()){
// 如果存在,则删除
// rootDir.delete(); // 仅能删除空目录
// 使用commons-io包提供的FileUtils工具类进行删除
try {
FileUtils.deleteDirectory(rootDir);
} catch (IOException e) {
e.printStackTrace();
}
}
// 创建根目录
rootDir.mkdirs();
// System.out.println(rootDir);
// ZipInputStream:用于进行zip格式的压缩文件输入流
try (ZipInputStream in = new ZipInputStream(new FileInputStream(sourceFile))) {
// 遍历压缩包中的每个子目录或子文件(ZipEntry类型的对象)
ZipEntry zipEntry = null;
while((zipEntry = in.getNextEntry()) != null){
// System.out.println(zipEntry.getName());
// 创建子目录或子文件(File对象)
// F:\Software\IDEA\Projects\test\easyftp-server-1.7.0.10-cn
File file = new File(rootDir.getPath()+"\\"+zipEntry.getName());
if(zipEntry.isDirectory()){
// 物理磁盘创建子目录
file.mkdirs();
}else{
// 物理磁盘创建子文件
file.createNewFile();
// 读取当前压缩包中的子文件,并通过输出流out写入新子文件中
try(FileOutputStream out = new FileOutputStream(file)) {
byte[] buff = new byte[1024];
int len = -1;
while((len = in.read(buff)) != -1){
out.write(buff,0,len);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
2.rar解压代码实现:
// 解压缩rar格式
private static void unrar(String path) {
// 1.创建解压缩的根目录
File rarFile = new File(path);
// File rootDir = new File(rarFile.getParent()+"\\"+rarFile.getName().substring(0,rarFile.getName().lastIndexOf(".")));
String rarFileName = rarFile.getName();
File rootDir = new File(rarFile.getParent()+"\\"+rarFileName.substring(0,rarFileName.lastIndexOf(".")));
if(rootDir.exists()){
try {
FileUtils.deleteDirectory(rootDir);
} catch (IOException e) {
e.printStackTrace();
}
}
rootDir.mkdirs();
// 创建Archive对象,用于读取rar压缩文件格式
try(Archive archive = new Archive(new FileInputStream(path))) {
// 读取压缩文件中的所有子目录或子文件(FileHeader对象)
List<FileHeader> fileHeaderList = archive.getFileHeaders();
// 按照子目录(子文件)名来排序
fileHeaderList.sort(new Comparator<FileHeader>() {
@Override
public int compare(FileHeader o1, FileHeader o2) {
return o1.getFileName().compareTo(o2.getFileName());
}
});
// 遍历子目录和子文件
for (FileHeader fd:fileHeaderList) {
System.out.println(fd.getFileName());
File f = new File(rootDir.getPath()+"\\"+fd.getFileName());
if(fd.isDirectory()){
// 创建新子目录
f.mkdirs();
}else{
// 创建新子文件
f.createNewFile();
// 获取压缩包中的子文件输出流
InputStream in = archive.getInputStream(fd);
// 复制文件输入流至新子文件
FileUtils.copyInputStreamToFile(in,f);
}
}
} catch (RarException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
3.调用解压方法:
最后,在main
方法或任何其他适当的位置调用unzip
方法,传入ZIP或RAR文件的路径和解压到的目标。
import com.github.junrar.Archive;
import com.github.junrar.exception.RarException;
import com.github.junrar.rarfile.FileHeader;
import org.apache.commons.io.FileUtils;
import java.io.*;
import java.util.Comparator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public static void main(String[] args) {
// String path = "F:\\Software\\IDEA\\Projects\\test\\easyftp-server-1.7.0.10-cn.zip";
String path = "F:\\Software\\IDEA\\Projects\\test\\实验案例.rar";
if(path.endsWith(".zip")) {
unzip(path);
} else if(path.endsWith(".rar")){
unrar(path);
}
}
二、注意事项
- 文件路径处理:在解压时,注意正确处理ZIP文件中的文件路径,以避免安全风险(如路径遍历攻击)。
- 异常处理:在解压过程中,可能会遇到文件读取错误、写入错误或权限问题,应妥善处理这些异常。
- 性能优化:对于大型ZIP文件,考虑使用更高效的IO操作和流控制来优化解压速度。
- 压缩用到的JAR包:需要使用第三方库,如commons-io包。
三、总结
- 在解压缩文件过程中,主要是对流的读取操作,注意进行异常处理,以及关闭流。
- 解压缩文件时,注意空文件夹的处理。