Java compression and decompression (1) JDK built-in zip operation

1. Basic introduction

Manipulating compressed files is also a technical point that is often used. For example, when exporting multiple files to the browser for download, it is necessary to add multiple files to the compressed file. On the one hand, multiple files can be downloaded at one time. On the other hand, it can also be Reduce the size of the downloaded file. However, JDK's built-in operation compression files only provide zip format (rar format is copyright protected, and 7z format should not have been born in the early version of JDK), which is relatively tasteless. Looking back at the beginning of the work, I have experienced using Java to decompress. Documents are more or less involved in some of the later work, but they are not comprehensive enough, deep enough, and not professional enough. In the second half of last year, there was a demand for decompressing files in batches. The open source implementation of Java-related compression and decompression has been practiced, and it is developed around the daily application of work. The common compressed file formats are: zip, 7z, rar, so the response gives a variety of implementations of these formats. This article first uses JDK Built-in compression and decompression zip format expansion, detailed below.

2. Compression implementation

2.1 Compression tools

package cn.chendd.compress;

import org.apache.commons.lang3.StringUtils;

import java.io.*;

/**
 * JDK中内置的zip压缩和解压缩实现
 *
 * @author chendd
 * @date 2023/3/4 19:50
 */
public class CompressZip {

    /**
     * 压缩文件或文件夹(递归压缩子层)
     * @param file 文件或文件夹
     * @param zipFile zip文件
     * @throws IOException 异常处理
     */
    public static void zip(File file, File zipFile) throws IOException {
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile) , Charset.forName("GBK"))) {
            generareZipFile(file, zos, file);
        }
    }

    /**
     * 压缩文件或文件夹(递归压缩子层)
     * @param file 文件或文件夹
     * @param zipFile zip文件
     * @param charset 编码
     * @param comment 备注
     * @throws IOException 异常处理
     */
    public static void zip(File file, File zipFile , String charset , String comment) throws IOException {
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile) , Charset.forName(charset))) {
            if (StringUtils.isNotEmpty(comment)) {
                zos.setComment(comment);
            }
            generareZipFile(file, zos, file);
        }
    }

    /**
     * 生成zip文件
     * @param inFile 原文件
     * @param zos 压缩流
     * @param rootFile 根文件
     * @throws IOException 异常处理
     */
    private static void generareZipFile(File inFile, ZipOutputStream zos, File rootFile) throws IOException {
        if (inFile.isFile()) {
            putEntryFile(zos, rootFile, inFile);
            return;
        }
        File[] files = inFile.listFiles();
        if (files == null || files.length == 0) {
            putEntryEmptyFolder(zos , inFile , rootFile);
            return;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                generareZipFile(file, zos, rootFile);
            } else {
                putEntryFile(zos, file, rootFile);
            }
        }
    }

    /**
     * 压缩空文件夹
     * @param zos 文件流
     * @param file 文件
     * @param rootFile 根文件
     * @throws IOException 异常处理
     */
    private static void putEntryEmptyFolder(ZipOutputStream zos, File file, File rootFile) throws IOException {
        String path = StringUtils.substringAfter(file.getAbsolutePath(), rootFile.getAbsolutePath() + File.separator);
        ZipEntry zipEntry;
        //处理空文件夹
        String folder = file.isDirectory() ? "/" : StringUtils.EMPTY;
        if (StringUtils.isBlank(path)) {
            zipEntry = new ZipEntry(file.getName() + folder);
        } else {
            zipEntry = new ZipEntry(path + folder);
        }
        zos.putNextEntry(zipEntry);
        zos.closeEntry();
        zos.flush();
    }

    /**
     * 压缩文件
     * @param zos 文件流
     * @param file 文件
     * @param rootFile 根文件
     * @throws IOException 异常处理
     */
    private static void putEntryFile(ZipOutputStream zos, File file, File rootFile) throws IOException {
        String path = StringUtils.substringAfter(file.getAbsolutePath(), rootFile.getAbsolutePath() + File.separator);
        ZipEntry zipEntry;
        if (StringUtils.isBlank(path)) {
            zipEntry = new ZipEntry(file.getName());
        } else {
            zipEntry = new ZipEntry(path);
        }
        zos.putNextEntry(zipEntry);
        Files.copy(file.toPath(), zos);
        zos.closeEntry();
        zos.flush();
    }

}

2.2 Compression tools test

package cn.chendd.compress;

import org.junit.*;

import java.io.*;

/**
 * 测试压缩zip
 *
 * @author chendd
 * @date 2023/3/4 20:44
 */
@RunWith(JUnit4.class)
public class CompressZipTest {

    /**
     * 测试压缩文件
     */
    @Test
    public void zipFile() throws IOException {
        File projectHome = new File(System.getProperty("user.dir")).getParentFile();
        File file = new File(projectHome , "源文件/哈喽.txt");
        File zipFile = new File(projectHome , "压缩文件夹/哈喽.zip");
        CompressZip.zip(file , zipFile);
        System.out.println("压缩源文件:" + file.getAbsolutePath());
        System.out.println("压缩后文件:" + zipFile.getAbsolutePath());
    }

    /**
     * 测试压缩文件夹
     */
    @Test
    public void zipFolder() throws IOException {
        File projectHome = new File(System.getProperty("user.dir")).getParentFile();
        File folder = new File(projectHome , "源文件/简单文件夹");
        File zipFile = new File(projectHome , "压缩文件夹/简单文件夹.zip");
        CompressZip.zip(folder , zipFile);
        System.out.println("压缩源文件:" + folder.getAbsolutePath());
        System.out.println("压缩后文件:" + zipFile.getAbsolutePath());
    }

    /**
     * 测试压缩复杂结构文件夹
     */
    @Test
    public void zipComplexFolder() throws IOException {
        File projectHome = new File(System.getProperty("user.dir")).getParentFile();
        File folder = new File(projectHome , "源文件/复杂文件夹");
        File zipFile = new File(projectHome , "压缩文件夹/复杂文件夹.zip");
        CompressZip.zip(folder , zipFile);
        System.out.println("压缩源文件:" + folder.getAbsolutePath());
        System.out.println("压缩后文件:" + zipFile.getAbsolutePath());
    }

}

3. Run the example

(single file compression)

(folder compression)

(Complex file structure compression)

4. Implementation instructions

(1) This article uses Java's built-in zip API to achieve file (folder) compression;

(2) This site once wrote the implementation of decompressing files (folders) using Java's built-in zip API, but it is very, very early. You can check it in the full-text search "Java Unzip Folder" on this site. Let's take a look. , after all, it was written a long time ago;

(3) This article mainly focuses on compressed files (folders), supports the compression of single files and folders, supports multiple files in a folder, including empty folders and empty files, and supports recursive compression of multiple folders at the same time;

(4) Support "Notes" for compressed files, and support compressed files (folders) containing Chinese names;

(5) Project source code download address: " https://gitee.com/88911006/chendd-examples/tree/master/compress ", see jdk module for details;

[For more professional implementations of Java compression and decompression, refer to the following articles]

Java compression and decompression (1) JDK built-in zip operation

Java compression and decompression (2) Zip4j practice

Java压缩和解压缩(三)Apache Commons Compress实践

Java压缩和解压缩(四)7-Zip-Jbinding实践

Java压缩和解压缩(五)小总结

Guess you like

Origin blog.csdn.net/haiyangyiba/article/details/129353130