JAVA 操作 zip


zip4j源码地址

 <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压缩包到指定目录
     * 

* 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出 * * @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("完成"); } }