<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>2.7.0</version>
</dependency>
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
/**
* 压缩与解压缩文件工具类
*
* @author wh
*/
public class ZipUtils {
/**
* 压缩文件 2 OutputStream
*
* @param outputStream outputStream
* @param filesToAdd 添加的文件
* @param password 设置密码
*/
public static void zipOutputStream(OutputStream outputStream, List<File> filesToAdd, String password) {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.DEFLATE);
zipParameters.setCompressionLevel(CompressionLevel.NORMAL);
if (StringUtils.isNotEmpty(password)) {
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setEncryptFiles(true);
}
try (ZipOutputStream zos = initializeZipOutputStream(outputStream, password)) {
for (File fileToAdd : filesToAdd) {
// Entry size has to be set if you want to add entries of STORE compression method (no compression)
// This is not required for deflate compression
if (zipParameters.getCompressionMethod() == CompressionMethod.STORE) {
zipParameters.setEntrySize(fileToAdd.length());
}
do_file_toZip(fileToAdd, zos, zipParameters, fileToAdd.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static ZipOutputStream initializeZipOutputStream(OutputStream outputStream, String password) throws IOException {
if (StringUtils.isNotEmpty(password)) {
return new ZipOutputStream(outputStream, password.toCharArray());
}
return new ZipOutputStream(outputStream);
}
private static void do_file_toZip(File sourceFile, ZipOutputStream zos, ZipParameters zipParameters, String name) throws Exception {
byte[] buf = new byte[4096];
if (sourceFile.isFile()) {
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
zipParameters.setFileNameInZip(name);
zos.putNextEntry(zipParameters);
// copy文件到zip输出流中
int readLen;
try (InputStream inputStream = new FileInputStream(sourceFile)) {
while ((readLen = inputStream.read(buf)) != -1) {
zos.write(buf, 0, readLen);
}
}
zos.closeEntry();
} else {
File[] listFiles = sourceFile.listFiles();
if (listFiles == null || listFiles.length == 0) {
// 需要保留原来的文件结构时,需要对空文件夹进行处理
zipParameters.setFileNameInZip(name + "/");
zos.putNextEntry(zipParameters);
zos.closeEntry();
} else {
for (File file : listFiles) {
// 判断是否需要保留原来的文件结构 注意:file.getName()前面需要带上父文件夹的名字加一斜杠, 不然最后压缩包中就不能保留原来的文件结构, 所有文件都跑到压缩包根目录下了
do_file_toZip(file, zos, zipParameters, name + "/" + file.getName());
}
}
}
}
/**
* 根据给定密码压缩文件(s)到指定目录
*
* @param destFileName 压缩文件存放绝对路径 e.g.:D:/upload/zip/demo.zip
* @param passwd 密码(可为空)
* @param files 单个文件或文件数组
* @return 最终的压缩文件存放的绝对路径, 如果为null则说明压缩失败.
*/
public static String compress(String destFileName, String passwd, File... files) {
try {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.DEFLATE);
zipParameters.setCompressionLevel(CompressionLevel.NORMAL);
zipParameters.setIncludeRootFolder(true);
ZipFile zipFile;
if (StringUtils.isNotBlank(passwd)) {
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
zipFile = new ZipFile(destFileName, passwd.toCharArray());
} else {
zipParameters.setEncryptFiles(false);
zipParameters.setEncryptionMethod(EncryptionMethod.NONE);
zipFile = new ZipFile(destFileName);
}
zipFile.setCharset(StandardCharsets.UTF_8);
for (File file : files) {
if (file.exists()) {
if (file.isDirectory()) {
zipFile.addFolder(file, zipParameters);
} else {
zipFile.addFile(file, zipParameters);
}
}
}
return destFileName;
} catch (ZipException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据给定密码压缩文件(s)到指定位置
*
* @param destFileName 压缩文件存放绝对路径 e.g.:D:/upload/zip/demo.zip
* @param passwd 密码(可为空)
* @param filePaths 单个文件路径或文件路径数组
* @return 最终的压缩文件存放的绝对路径, 如果为null则说明压缩失败.
*/
public static String compress(String destFileName, String passwd, String... filePaths) {
int size = filePaths.length;
File[] files = new File[size];
for (int i = 0; i < size; i++) {
files[i] = new File(filePaths[i]);
}
return compress(destFileName, passwd, files);
}
/**
* 根据给定密码压缩文件(s)到指定位置
*
* @param destFileName 压缩文件存放绝对路径 e.g.:D:/upload/zip/demo.zip
* @param passwd 密码(可为空)
* @param folder 文件夹
* @return 最终的压缩文件存放的绝对路径, 如果为null则说明压缩失败.
*/
public static String compressFolder(String destFileName, String passwd, File folder) {
if (folder.exists()) {
File[] files = folder.listFiles();
// 遍历folder文件夹下所有的文件、文件夹
return compress(destFileName, passwd, files);
}
return null;
}
/**
* 根据所给密码解压zip压缩包到指定目录
* <p>
* 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
*
* @param zipFile zip压缩包绝对路径
* @param dest 指定解压文件夹位置
* @param passwd 密码(可为空)
* @return 解压后的文件数组
* @throws ZipException
*/
public static File[] deCompress(File zipFile, String dest, String passwd) throws ZipException {
// 1.判断指定目录是否存在
File destDir = new File(dest);
if (destDir.isDirectory() && !destDir.exists()) {
destDir.mkdir();
}
// 2.初始化zip工具
ZipFile zFile = new ZipFile(zipFile);
zFile.setCharset(StandardCharsets.UTF_8);
if (!zFile.isValidZipFile()) {
throw new ZipException("压缩文件不合法,可能被损坏.");
}
// 3.判断是否已加密
if (zFile.isEncrypted()) {
zFile.setPassword(passwd.toCharArray());
}
// 4.解压所有文件
zFile.extractAll(dest);
List<FileHeader> headerList = zFile.getFileHeaders();
List<File> extractedFileList = new ArrayList<>();
for (FileHeader fileHeader : headerList) {
if (!fileHeader.isDirectory()) {
extractedFileList.add(new File(destDir, fileHeader.getFileName()));
}
}
File[] extractedFiles = new File[extractedFileList.size()];
extractedFileList.toArray(extractedFiles);
return extractedFiles;
}
/**
* 解压无密码的zip压缩包到指定目录
*
* @param zipFile zip压缩包
* @param dest 指定解压文件夹位置
* @return 解压后的文件数组
* @throws ZipException
*/
public static File[] deCompress(File zipFile, String dest) {
try {
return deCompress(zipFile, dest, null);
} catch (ZipException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据所给密码解压zip压缩包到指定目录
*
* @param zipFilePath zip压缩包绝对路径
* @param dest 指定解压文件夹位置
* @param passwd 压缩包密码
* @return 解压后的所有文件数组
*/
public static File[] deCompress(String zipFilePath, String dest, String passwd) {
try {
return deCompress(new File(zipFilePath), dest, passwd);
} catch (ZipException e) {
e.printStackTrace();
}
return null;
}
/**
* 无密码解压压缩包到指定目录
*
* @param zipFilePath zip压缩包绝对路径
* @param dest 指定解压文件夹位置
* @return 解压后的所有文件数组
*/
public static File[] deCompress(String zipFilePath, String dest) {
try {
return deCompress(new File(zipFilePath), dest, null);
} catch (ZipException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws IOException {
// 压缩demo1 自定义文件夹
// 创建一个 rootTemp 缓存目录
String rootTemp = "D:/xxxproject";
// 获取缓存目录文件夹下的全部文件结构和数据
File file = new File(rootTemp);
//模拟添加多个文件夹目录
for (int i = 0; i < 3; i++) {
// 需要被压缩的源文件
File file1 = new File("D:/test.xls");
// 自定义文件夹
File file2 = new File(rootTemp + "/" + i + "/a1/a2");
// 将源文件复制到自定义文件夹内, 有多个文件的的话都复制进来
FileUtils.copyFileToDirectory(file1, file2);
// 模拟创建空文件夹
File file3 = new File(rootTemp + "/" + i + "/b1/b2");
file3.mkdirs();
}
compressFolder(rootTemp + ".zip", "", file);
// 压缩后删除缓存目录全部的数据
FileUtils.deleteDirectory(file);
//压缩demo2 到OutputStream
List<File> list = new ArrayList<>();
list.add(new File("D:/360SoftMgrGame"));
zipOutputStream(new FileOutputStream("D:/sign.zip"), list, "");
// 解压
//deCompress("D:/sign.zip", "D:/unzip", "");
System.err.println("完成");
}
}
JAVA 操作 zip
最新推荐文章于 2022-12-01 10:13:11 发布