Java解压压缩包(zip/rar/7z)
一、概述
主要实现解压压缩包,拿到压缩包中每个文件。
二、思路
针对压缩包的操作,首先需要拿到压缩包文件的流,然后利用第三方工具将流实例化,调用next方法迭代,然后分别操作压缩包中的单个文件。
三、代码实现
1.zip实现
jdk支持对zip流的操作,相关依赖在java.util.zip下
// 获取本地zip包
public void unzipByPath() {
try {
String localPath = "D:\\文件.zip";
File file = new File(localPath);
ZipInputStream zin; // 创建ZipInputStream对象
InputStream inputStream = new FileInputStream(file);
zin = new ZipInputStream(inputStream, Charset.forName("GBK")); // 实例化对象,指明要解压的文件
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null) {
System.out.println(zipEntry.getName());
BufferedInputStream bs = new BufferedInputStream(zin);
// 将文件信息写到byte数组中
byte[] bytes = new byte[(int) entry.getSize()];
bs.read(bytes, 0, (int) entry.getSize());
if ("zip".equals(entry.getName().substring(entry.getName().lastIndexOf(".") + 1))) {
ZipInputStream secondZip = new ZipInputStream(new ByteArrayInputStream(bytes), Charset.forName("GBK"));
// 循环解压
}
}
zin.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取远程zip包
public void unzipByUrl() {
String fileUrl = "https://localhost:80/group1/M00/6D/A3/wKjScWE7PxqAQfUnAAGcIyZy0ZU422.zip";
try {
URL url = new URL(fileUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
int resultCode = conn.getResponseCode();
if (200 == resultCode) {
ZipInputStream zipInputStream = new ZipInputStream(conn.getInputStream(), Charset.forName("GBK"));
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
System.out.println(zipEntry.getName());
BufferedInputStream bs = new BufferedInputStream(zipInputStream);
// 将文件信息写到byte数组中
byte[] bytes = new byte[(int) zipEntry.getSize()];
bs.read(bytes, 0, (int) zipEntry.getSize());
if ("zip".equals(zipEntry.getName().substring(zipEntry.getName().lastIndexOf(".") + 1))) {
ZipInputStream secondZip = new ZipInputStream(new ByteArrayInputStream(bytes), Charset.forName("GBK"));
// 循环解压
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
2.rar实现
1)依赖
<!-- 解压rar所需的依赖 -->
<dependency>
<groupId>com.github.junrar</groupId>
<artifactId>junrar</artifactId>
<version>4.0.0</version>
</dependency>
2)代码
// 获取本地rar
public void unRarByPath() {
String rarPath = "D:\\文件.rar";
try {
File outFileDir = new File(rarPath);
Archive archive = new Archive(new FileInputStream(rarFile));
FileHeader fileHeader;
while ((fileHeader = archive.nextFileHeader()) != null) {
// 解决文件名中文乱码问题
String fileName = fileHeader.getFileNameW().isEmpty() ? fileHeader.getFileNameString() :
fileHeader.getFileNameW();
String fileExt =
fileName.substring(fileName.lastIndexOf(FileConstant.FILE_SEPARATOR) + 1);
System.out.println(fileName);
ByteArrayOutputStream os = new ByteArrayOutputStream();
archive.extractFile(fileHeader, os);
// 将文件信息写到byte数组中
byte[] bytes = os.toByteArray();
System.out.println(bytes.length);
if ("rar".equals(fileExt)) {
Archive secondArchive = new Archive(new ByteArrayInputStream(bytes));
// 循环解压
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 获取远程rar
public void unRarByUrl() {
String rarUrl = "https://localhost:80/group1/M00/6D/A3/wKjScWE7PxqAQfUnAAGcIyZy0ZU422.rar";
try {
URL url = new URL(rarUrl);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
int resultCode = conn.getResponseCode();
if (200 == resultCode) {
InputStream inputStream = conn.getInputStream();
Archive archive = new Archive(inputStream);
FileHeader fileHeader;
while ((fileHeader = archive.nextFileHeader()) != null) {
// 解决文件名中文乱码问题
String fileName = fileHeader.getFileNameW().isEmpty() ? fileHeader.getFileNameString() :
fileHeader.getFileNameW();
String fileExt =
fileName.substring(fileName.lastIndexOf(FileConstant.FILE_SEPARATOR) + 1);
System.out.println(fileName);
ByteArrayOutputStream os = new ByteArrayOutputStream();
archive.extractFile(fileHeader, os);
// 将文件信息写到byte数组中
byte[] bytes = os.toByteArray();
System.out.println(bytes.length);
if ("rar".equals(fileExt)) {
Archive secondArchive = new Archive(new ByteArrayInputStream(bytes));
// 循环解压
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
3)注意
rar5的加密算法未开源,目前不支持对rar5的解压,建议压缩时选择rar4
3.7z实现
由于7z的算法等原因,目前只有针对文件的解压,不能直接对流进行操作
<!--apache提供的压缩包依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.9</version>
</dependency>
<!--不引入xz依赖会在new SevenZFile的时候报错java.lang.NoClassDefFoundError: org/tukaani/xz/FilterOptions-->
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.5</version>
</dependency>
// 解析本地7z文件
public void un7zByPath() {
File srcFile = new File("C:\\文件.7z");//获取当前压缩文件
//开始解压
try {
SevenZFile zIn = new SevenZFile(srcFile);
SevenZArchiveEntry entry = null;
File newFile = null;
while ((entry = zIn.getNextEntry()) != null) {
if (!entry.isDirectory()) {
newFile = new File("destDirPath", entry.getName());
if (!newFile.exists()) {
new File(newFile.getParent()).mkdirs();//创建此文件的上级目录
}
OutputStream out = new FileOutputStream(newFile);
BufferedOutputStream bos = new BufferedOutputStream(out);
int len = -1;
// 将文件信息写到byte数组中
byte[] buf = new byte[(int) entry.getSize()];
while ((len = zIn.read(buf)) != -1) {
bos.write(buf, 0, len);
}
System.out.println(entry.getName() + "=" + Arrays.toString(buf));
// 关流顺序,先打开的后关闭
bos.close();
out.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
实在不行可以考虑把远程文件写到磁盘再读成文件,不过这种方法不太靠谱,暂不考虑
四、总结
有关rar5不能解析,以及7z不能直接对流进行操作,后面找到解决方法再写