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();
    }
}

posted @ 2021-12-27 23:14  kayj  阅读(273)  评论(0编辑  收藏  举报