commons-compress
依赖
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-compress</artifactId> <version>1.21</version> </dependency>
官方文档
Commons Compress – Commons Compress User Guide
使用
解压zip包
注:多层,中文可以使用ZipArchiveInputStream但读入在mkdir和生成文件时会出错(乱码)
ZipInputStream无法读入中文文件名的文件盒文件夹,抛出异常报错
/**
* 解压zip包至目标目录下,若目录不存在会自动新建;
* utf-8编码的zip文件中存在gbk编码的文件和文件夹,解码会有乱码
* 文件夹名称存在中文的,新建文件夹会失败,采取跳过的策略
* 若存在中文命名的文件会抛出异常,采取跳过的策略
* @param inputStream 输入的文件流
* @Param destDir 解压的目标地址
*/
public void unzip(InputStream inputStream, String destDir) {
ArchiveEntry zipEntry;
try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
ZipArchiveInputStream zipInputStream = new ZipArchiveInputStream(bufferedInputStream)) {
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
File file = new File(destDir, zipEntry.getName());
if (zipEntry.isDirectory()) {
boolean mkdirs = file.mkdirs();
if (!mkdirs) {
log.info("make dir fails, dir exists Chinese");
}
} else {
try (FileOutputStream outPut = FileUtils.openOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outPut)) {
IOUtils.copy(zipInputStream, bufferedOutputStream, 8192);
} catch (IOException e) {
log.info("file exists Chinese");
}
}
}
} catch (IOException e) {
log.info("have an IOException", e);
throw new RuntimeException("解压失败", e);
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
log.info("failed to close the input stream");
}
}
}
压缩多层文件到zip包中(使用ZipOutputStream,非commons-compress库的使用)
/**
* 压缩文件(文件夹)为zip包
* @param sourceFile
* @param targetZipFile
* @param base
* @throws IOException
*/
public void zipFiles(File sourceFile, File targetZipFile, String base) throws IOException {
ZipOutputStream outputStream = null;
try {
outputStream = new ZipOutputStream(new FileOutputStream(targetZipFile));
for (File file : sourceFile.listFiles()) {
addEntry("", file, outputStream, base);
}
} catch (Exception e) {
throw new IOException(e);
} finally {
outputStream.close();
}
}
private void addEntry(String dir, File inFile, ZipOutputStream out, String base) throws IOException {
if (inFile.isDirectory()) {
File[] files = inFile.listFiles();
if (files != null && files.length > 0) {
for (File file : files) {
String name = inFile.getName();
if (!"".equals(dir)) {
name = dir + "/" + name;
}
addEntry(name, file, out, base);
}
}
} else {
doZip(inFile, out, dir, base);
}
}
private void doZip(File inFile, ZipOutputStream out, String dir, String base) throws IOException {
String entryName = null;
if (!"".equals(dir)) {
entryName = dir + "/" + inFile.getName();
} else {
entryName = inFile.getName();
}
log.info("zip entryName is "+entryName);
ZipEntry entry = new ZipEntry(entryName);
out.putNextEntry(entry);
int len = 0 ;
byte[] buffer = new byte[1024];
FileInputStream fis = new FileInputStream(inFile);
while ((len = fis.read(buffer)) > 0) {
out.write(buffer, 0, len);
out.flush();
}
out.closeEntry();
fis.close();
}
压缩单个或多层文件到zip包中(使用ZipArchiveOutputStream)
/**
* 支持单文件或多层文件夹的压缩
*
* @param srcPath
* @param targetPath
*/
public static void zipFile(String srcPath, String targetPath) {
int length;
File file = new File(srcPath);
List<File> filesToArchive;
if (file.isDirectory()) {
filesToArchive = getAllFile(new File(srcPath));
length= srcPath.length();
} else {
filesToArchive = Collections.singletonList(file);
length = file.getParent().length()+1;
}
try (ArchiveOutputStream o = new ZipArchiveOutputStream(new File(targetPath))) {
for (File f : filesToArchive) {
ArchiveEntry entry = o.createArchiveEntry(f, f.getPath().substring(length));
o.putArchiveEntry(entry);
if (f.isFile()) {
try (InputStream i = Files.newInputStream(f.toPath())) {
IOUtils.copy(i, o);
}
}
o.closeArchiveEntry();
}
} catch (IOException e) {
logger.error("zipFile fails", e);
}
}
public static List<File> getAllFile(File dirFile) {
File[] childrenFiles = dirFile.listFiles();
if (Objects.isNull(childrenFiles) || childrenFiles.length == 0) {
return Collections.emptyList();
}
List<File> files = new ArrayList<>();
for (File childFile : childrenFiles) {
if (childFile.isFile()) {
files.add(childFile);
} else {
files.add(childFile);
List<File> cFiles = getAllFile(childFile);
if (cFiles.isEmpty()) {
continue;
}
files.addAll(cFiles);
}
}
return files;
}
使用
@Test
public void testZipFile_use_file() {
String srcPath = "D:/log/aa/QueryResult1656385398596.csv";
String targetPath = "D:/log/aa/tmp.zip";
ZipUtil.zipFile(srcPath,targetPath);
}
@Test
public void testZipFile_use_dir() {
String srcPath = "D:/log/aa/";
String targetPath = "D:/log/aa/tmp.zip";
ZipUtil.zipFile(srcPath,targetPath);
}