zip文件压缩
https://zhuanlan.zhihu.com/p/364142487
https://juejin.cn/post/6952794190107377677
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.20</version>
</dependency>
package com.vgrass.ipauth.common.util;
import com.vgrass.ipauth.common.spring.SpringUtils;
import org.apache.commons.compress.archivers.zip.ParallelScatterZipCreator;
import org.apache.commons.compress.archivers.zip.UnixStat;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.parallel.InputStreamSupplier;
import org.apache.commons.io.input.NullInputStream;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 文件压缩
*
*/
public class FileZipUtils {
private static final int BUFF_SIZE = 4096;
/**
* 仅压缩文件,不包括文件夹,如果有文件层次结构通过fileName进行实现
*
* @param file
* @param fileName
* @param outputStream
* @throws IOException
*/
public static void compressFile(File file, String fileName, final ZipOutputStream outputStream) throws IOException {
//创建文件
outputStream.putNextEntry(new ZipEntry(fileName));
//读取文件并写出
FileInputStream fileInputStream = new FileInputStream(file);
int len = 0;
byte[] buff = new byte[BUFF_SIZE];
while ((len = fileInputStream.read(buff)) != -1) {
outputStream.write(buff, 0, len);
}
fileInputStream.close();
}
/**
* 批量压缩文件 v2.0
*
* @param fileNames 需要压缩的文件名称列表(包含相对路径)
* @param zipOutName 压缩后的文件名称
**/
public static void batchZipFilesV2(List<String> fileNames, String zipOutName) throws Exception {
ZipOutputStream zipOutputStream = null;
WritableByteChannel writableByteChannel = null;
ByteBuffer buffer = ByteBuffer.allocate(BUFF_SIZE);
try {
zipOutputStream = new ZipOutputStream(new FileOutputStream(zipOutName));
writableByteChannel = Channels.newChannel(zipOutputStream);
for (String sourceFile : fileNames) {
File source = new File(sourceFile);
zipOutputStream.putNextEntry(new ZipEntry(source.getName()));
FileChannel fileChannel = new FileInputStream(sourceFile).getChannel();
while (fileChannel.read(buffer) != -1) {
//更新缓存区位置
buffer.flip();
while (buffer.hasRemaining()) {
writableByteChannel.write(buffer);
}
buffer.rewind();
}
fileChannel.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
zipOutputStream.close();
writableByteChannel.close();
buffer.clear();
}
}
/**
* 批量压缩文件 v4.0
*
* @param zipOutName 压缩后的文件名称
* @param fileNameList 需要压缩的文件名称列表(包含相对路径)
**/
public static void compressFileList(String zipOutName, List<String> fileNameList) throws IOException, ExecutionException, InterruptedException {
// 新建线程池,在压缩结束时会close线程导致没法重复利用
ExecutorService fixedExecutorService = Executors.newFixedThreadPool(4);
ParallelScatterZipCreator parallelScatterZipCreator = new ParallelScatterZipCreator(executor);
OutputStream outputStream = new FileOutputStream(zipOutName);
ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(outputStream);
zipArchiveOutputStream.setEncoding("UTF-8");
for (String fileName : fileNameList) {
File inFile = new File(fileName);
final InputStreamSupplier inputStreamSupplier = () -> {
try {
return new FileInputStream(inFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
return new NullInputStream(0);
}
};
ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(inFile.getName());
zipArchiveEntry.setMethod(ZipArchiveEntry.DEFLATED);
zipArchiveEntry.setSize(inFile.length());
zipArchiveEntry.setUnixMode(UnixStat.FILE_FLAG | 436);
parallelScatterZipCreator.addArchiveEntry(zipArchiveEntry, inputStreamSupplier);
}
parallelScatterZipCreator.writeTo(zipArchiveOutputStream);
zipArchiveOutputStream.close();
outputStream.close();
}
}