Java 实现 7z 格式的压缩与解压

7z 是一种主流高效的压缩格式,它拥有极高的压缩比。而且 7-Zip 是一款开源软件,大部分源代码遵循 GNU LGPL License,使用 7-Zip 软件,无需注册,免费,是真正意义的 free and open,因此得到很多人的选择。

本代码可支持多个文件或文件夹的压缩与解压。

1,依赖 commons-compress 包:

1
2
3
4
5
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.18</version>
</dependency>

2,实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Logger;

import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;

/**
* 7z 压缩和解压工具类
*/
public class SevenZUtil {

private static final Logger logger = Logger.getLogger(SevenZUtil.class.getName());

/**
* 压缩多个文件到 7z 文件
* @param compressFilePath 生成的 7z 文件路径
* @param inputFiles 多个需要加入压缩的文件,支持文件夹。
* @return
*/
public static void compress7z(String compressFilePath, File... inputFiles) throws IOException {
if (inputFiles.length == 0) {
throw new RuntimeException("InputFiles is null.");
}
for (File inputFile : inputFiles) {
if (!inputFile.exists()) {
throw new RuntimeException("InputFile:" + inputFile.getPath() + "not exists.");
}
}
File compressFile = new File(compressFilePath);
if (compressFile != null && compressFile.exists()) {
throw new RuntimeException("7zFile:" + compressFile.getPath() + "exists.");
}
SevenZOutputFile sevenZOutput = new SevenZOutputFile(compressFile);
try {
for (File inputFile : inputFiles) {
compress(sevenZOutput, inputFile, null);
}
} finally {
sevenZOutput.close();
}
}

private static void compress(SevenZOutputFile sevenZOutput, File inputFile, String name) throws IOException {
if (name == null) {
name = inputFile.getName();
}

if (inputFile.isDirectory()) { // 目录
File[] childFiles = inputFile.listFiles();
if (childFiles.length == 0) {
SevenZArchiveEntry entry = sevenZOutput.createArchiveEntry(inputFile, name);
sevenZOutput.putArchiveEntry(entry);
sevenZOutput.closeArchiveEntry();
logger.info("Compress dir:" + inputFile.getPath());
} else {
for (File childFile : childFiles) {
compress(sevenZOutput, childFile, name + File.separator + childFile.getName());
}
}
} else { // 单个文件
BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(inputFile));
SevenZArchiveEntry entry = sevenZOutput.createArchiveEntry(inputFile, name);
sevenZOutput.putArchiveEntry(entry);
int len = -1;
byte[] buffer = new byte[2048];
while ((len = inputStream.read(buffer)) != -1) {
sevenZOutput.write(buffer, 0, len);
}
inputStream.close();
sevenZOutput.closeArchiveEntry();
logger.info("Compress file:" + inputFile.getPath());
}
}

/**
* 解压 7z 文件
* @param compressFilePath 7z 文件路径
* @param outputDir 解压目标目录
* @return
*/
public static void unCompress7z(String compressFilePath, String outputDir) throws IOException {
File compressFile = new File(compressFilePath);
if (compressFile == null || !compressFile.exists()) {
throw new RuntimeException("7zFile not exists.");
}

File output = new File(outputDir);
if (output == null || !output.exists() || !output.isDirectory()) {
throw new RuntimeException("Invalid outputDir:" + outputDir);
}

// 循环解压
SevenZFile sevenZFile = new SevenZFile(compressFile);
SevenZArchiveEntry entry = null;
while ((entry = sevenZFile.getNextEntry()) != null) {
String newFilePath = outputDir + File.separator + entry.getName();
File newFile = new File(newFilePath);

// 处理目录
if (entry.isDirectory()) {
boolean mkdirs = newFile.mkdirs();
if (!mkdirs) {
throw new RuntimeException("Fail mkdir:" + newFilePath);
}
logger.info("Mkdir:" + newFilePath);
continue;
}

// 解压文件
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(newFile);
int length = 0;
byte[] buffer = new byte[2048];
while ((length = sevenZFile.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
logger.info("UnCompress file:" + newFilePath);
} catch (Exception e) {
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
}
}
}
}