Zip4j解压文件

使用 zip4j 可以快速对文件进行解压缩处理

更多精彩

官网

  1. GitHub - srikanth-lingala/zip4j: A Java library for zip files and streams

特性

  1. 支持Zip文件的创建、添加、解压、更新、移除
  2. 可读写有密码保护的Zip文件
  3. 支持AES 128/256算法加密
  4. 支持标准Zip算法加密
  5. 支持Zip64格式
  6. 支持分块Zip文件的创建和解压
  7. 支持Unicode编码的文件名
  8. 支持进度监控

添加Maven依赖

1
2
3
4
5
<dependency>
    <groupId>net.lingala.zip4j</groupId>
    <artifactId>zip4j</artifactId>
    <version>1.3.2</version>
</dependency>

直接解压文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 获取Zip文件
ZipFile zipFile = new ZipFile(filePath);
// 指定文件名编码
zipFile.setFileNameCharset("GBK");

// 验证文件有效性
if (!zipFile.isValidZipFile()) {
    return;
}

// 解压目录
File fileDir = new File(destPath);

// 目录不存在则创建
if (fileDir.isDirectory() && !fileDir.exists()) {
    fileDir.mkdir();
}

// 解压
zipFile.extractAll(destPath);

解压并过滤部分文件

解压操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void unzipFile(File file, String destPath) throws ZipException, IOException {
    ZipFile zipFile = new ZipFile(file);

    zipFile.setFileNameCharset(GBK);

    if (!zipFile.isValidZipFile()) {
        return;
    }

    // 解压目录
    File fileDir = new File(destPath);

    if (fileDir.exists()) {
        FileUtils.deleteDirectory(fileDir);
    }

    if (fileDir.isDirectory() && !fileDir.exists()) {
        fileDir.mkdir();
    }

    // 解压之前先过滤
    filterZipFile(zipFile, destPath);
}

过滤文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void filterZipFile(ZipFile zipFile, String destPath) throws ZipException {
    List fileHeaders = zipFile.getFileHeaders();

    for (Object objFileHeader : fileHeaders) {
        FileHeader fileHeader = (FileHeader) objFileHeader;
        String fileName = fileHeader.getFileName();

        // 匹配到是需要过滤的文件则跳过
        if (isIllegalFile(fileName)) {
            continue;
        }

        // 匹配到隐藏文件则跳过
        if (isHiddenFile(fileName)) {
            continue;
        }

        zipFile.extractFile(fileHeader, destPath);
    }
}

检测需要过滤的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
private boolean isIllegalFile(String targetFileName) {
    String[] filterFileNames = new String[]{node_modules, target, out};

    for (String filterFileName : filterFileNames) {
        String fullSourceFileName = String.format("/%s/", filterFileName);

        if (targetFileName.contains(fullSourceFileName)) {
            return true;
        }
    }

    return false;
}

检测隐藏文件

1
2
3
4
5
6
private boolean isHiddenFile(String targetFileName) {
    Pattern hiddenFilePattern = Pattern.compile("/\.\w+");
    Matcher matcher = hiddenFilePattern.matcher(targetFileName);

    return matcher.find();
}

压缩文件

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
public File getOrCreateZipFile(String fullFilePath) {
    File file = new File(fullFilePath);

    // 文件存在
    if (file.exists() && file.isFile()) {
        return file;
    }

    // 从文件路径中截取文件后缀
    int prefixMark = fullFilePath.lastIndexOf(".");
    String filePath = fullFilePath.substring(0, prefixMark);

    // 尝试获取解压后的文件目录
    file = new File(filePath);

    // 不存在则说明确实没有该文件,直接返回
    if (!file.exists()) {
        return file;
    }

    try {
        // 创建压缩包
        ZipFile zipFile = new ZipFile(fullFilePath);
        ZipParameters zipParameters = new ZipParameters();
        zipParameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
        zipParameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
        zipParameters.setIncludeRootFolder(false);

        zipFile.addFolder(file, zipParameters);

        // 将文件从新指定位压缩文件
        file = new File((fullFilePath));
    } catch (ZipException e) {
        logger.error("文件压缩失败,teacherId -> {}, fullFilePath -> {}", super.getMemberId(), fullFilePath);
    }

    return file;
}