本文介绍使用最广泛的zip以及rar两种压缩包的处理方式。先介绍使用jdk本体就可以解压的zip。
zip处理方式
public static void main(String[] args) {
//字符串中填写你的压缩包路径
String path = "E:\\Codes\\Java_works\\excise-basic\\src\\javaSE_exise\\javaIO练习\\easyftp-server-1.7.0.10-cn.zip";
if (path.endsWith(".zip")) {
unzip(path);
} else if (path.endsWith(".rar")) {
unrar(path);
}
}
主方法中需要根据后缀名来判断解压的是zip文件还是rar文件
zip文件则调用unzip()方法
方法如下:
public static void unzip(String path) {
// 根据原始路径(path),创建源文件(File对象)
File sourceFile = new File(path);
// 创建根目录
// 获取文件名
String name = sourceFile.getName()
.substring(0, sourceFile.getName().lastIndexOf("."));// 包括了后缀名(但是我们不需要后缀名)
// 创建解压文件夹目录与压缩文件同目录,所以就要在上级目录开始创建
File rootDir = new File(sourceFile.getParent() + "\\" + name);
if (rootDir.exists()) {
// 存在就删除
// rootDir.delete();//普通删除如果目录中含有文件或者子目录就无法删除
try {
FileUtils.deleteDirectory(rootDir);
} catch (IOException e) {
e.printStackTrace();
}
}
// 删除后创建文件夹
rootDir.mkdir();
// 读压缩文件.zip内的文件 使用ZipInputSream
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(path));) {
// 压缩包中每个子目录或者文件就是ZipEntry对象
ZipEntry zipEntry = null;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
System.out.println(zipEntry.getName());
// 将读到的文件以及文件夹新建在之前存放解压文件的目录下rootDir
File file = new File(rootDir.getPath() + "\\" + zipEntry.getName());
// 判断解压的是文件还是文件夹
if (zipEntry.isDirectory()) {
file.mkdir();
} else {
// 创建完文件之后写入内容
file.createNewFile();
// 使用FIleOutputSream输出当前文件
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
byte[] buff = new byte[1024];
int len = -1;
// 将读到的字节存储在数组中
while ((len = zipInputStream.read()) != -1) {
fileOutputStream.write(buff, 0, len);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
要点如下:
1.getName()方法会获得文件全名包括后缀名,所以在开始创建解压根目录时,需要对获得到的文件名进行截取。
2.File类型使用delete()方法只可以删除空文件夹,需要借助commons包的中FileUtils类的deleteDirectory(File file)方法。
3.zip文件需要使用ZipInputStream类,使用FileInputStream类实例,因为不管读取什么文件本质上都要使用FileInputStream去读取。
4.压缩包中的每个文件或文件夹,都是一个ZipEntry对象,需要对ZipEntry对象进行判断,使用isDirectory()方法,如果为真则说明是一个当前ZipEntry对象是一个文件夹,就需要在解压根目录下创建文件夹,否则说明是文件,将读到的字节存入字符数组使用FileOutputStream中的write(写出的字节数组,从哪里开始,到哪里结束)方法写出。
rar的处理方式
相较于zip,rar处理需要使用第三方的jar包分别为slf4j-api、junrar。
main方法写法同上,此处只介绍unrar()方法如何实现
方法如下:
public static void unrar(String path) {
// 创建解压的源文件的根目录
File file = new File(path);
String name = file.getName().substring(0, file.getName().lastIndexOf("."));
File rootDir = new File(file.getParent() + "\\" + name);
if (rootDir.exists()) {
try {
FileUtils.deleteDirectory(rootDir);
} catch (IOException e) {
e.printStackTrace();
}
}
rootDir.mkdir();
// 读取rar压缩包内的文件 创建Archive对象
try (Archive archive = new Archive(new FileInputStream(path))) {
// 获取压缩文件中的所有子目录子文件FileHeader对象
List<FileHeader> fileHeadersList = archive.getFileHeaders();
// 按照子目录子文件名称排序
fileHeadersList.sort(new Comparator<FileHeader>() {
// 自定义排序规则
@Override
public int compare(FileHeader o1, FileHeader o2) {
return o1.getFileName().compareTo(o2.getFileName());
}
});
for (FileHeader fileHeader : fileHeadersList) {
System.out.println(fileHeader.getFileName());
File f = new File(rootDir.getPath() + "\\" + fileHeader.getFileName());
if (fileHeader.isDirectory()) {
f.mkdir();
} else {
f.createNewFile();
// 读入文件流
InputStream inputStream = archive.getInputStream(fileHeader);
// 将读入文件的流写在根目录文件对象上
FileUtils.copyInputStreamToFile(inputStream, f);
}
}
} catch (RarException | IOException e) {
e.printStackTrace();
}
}
要点如下:
1.Archive 就类似于java自带的ZipInputStream,同样是读取文件自然也需要使用FileInputStream来实例。
2.读取rar中的文件或文件夹实体可以直接使用Archive中getFileHeaders()方法,这种遍历方法深度优先找不到上一级目录,所以我们需要对其进行从排序。此处从写Comparator中的compare方法,自定义排序规则,这里用比较字符串来排序。
3.获得压缩包内实体后,进行遍历,将每个实体实例为File对象,判断是文件夹还是文件,此步骤同上。rar写入数据与zip有所不,使用Archive获取输入流之后,不用像zip一样边读边写,而是直接将文件输入流复制到文件对象上。