zip压缩和解压缩文件,支持多级压缩

末鹿安然 提交于 2021-01-21 17:39:43
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
    <version>1.20</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.8.0</version>
</dependency>
import org.apache.commons.compress.archivers.zip.*;
import org.apache.commons.compress.parallel.InputStreamSupplier;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

/**
 * 压缩类
 * @author tanlei
 */
public class CompressZip {

    private String rootPath;

    ParallelScatterZipCreator scatterZipCreator = new ParallelScatterZipCreator();
    // ParallelScatterZipCreator api says:
    // 注意这个类不保证写入到输出文件的顺序。需要保持特定顺序的(manifests,文件夹)必须使用这个类的客户类进行处理
    // 通常的做法是 在调用这个类的writeTo方法前把这些东西写入到ZipArchiveOutputStream
    ScatterZipOutputStream dirs = ScatterZipOutputStream
            .fileBased(File.createTempFile("whatever-preffix", ".whatever"));


    public CompressZip(String rootPath) throws IOException {
        this.rootPath = rootPath;
    }

    public CompressZip() throws IOException {
    }

    public void addEntry(final ZipArchiveEntry zipArchiveEntry, final InputStreamSupplier streamSupplier)
            throws IOException {
        if (zipArchiveEntry.isDirectory() && !zipArchiveEntry.isUnixSymlink()) {
            dirs.addArchiveEntry(ZipArchiveEntryRequest.createZipArchiveEntryRequest(zipArchiveEntry, streamSupplier));
        } else {
            scatterZipCreator.addArchiveEntry(zipArchiveEntry, streamSupplier);
        }
    }

    public void writeTo(final ZipArchiveOutputStream zipArchiveOutputStream)
            throws IOException, ExecutionException, InterruptedException {
        dirs.writeTo(zipArchiveOutputStream);
        dirs.close();
        scatterZipCreator.writeTo(zipArchiveOutputStream);
    }

    public String getRootPath() {
        return rootPath;
    }

    public void setRootPath(String rootPath) {
        this.rootPath = rootPath;
    }
}
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
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.util.zip.ZipEntry;

/**
 * 压缩类
 * @author tanlei
 */
public class ZipFileUtil {

    static class CustomInputStreamSupplier implements InputStreamSupplier {
        private File currentFile;

        public CustomInputStreamSupplier(File currentFile) {
            this.currentFile = currentFile;
        }

        @Override
        public InputStream get() {
            try {
                // InputStreamSupplier api says:
                // 返回值:输入流。永远不能为Null,但可以是一个空的流
                return currentFile.isDirectory() ? new NullInputStream(0) : new FileInputStream(currentFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
    }


    private static void addEntry(String entryName, File currentFile, CompressZip scatterSample) throws IOException {
        ZipArchiveEntry archiveEntry = new ZipArchiveEntry(entryName);
        archiveEntry.setMethod(ZipEntry.DEFLATED);
        final InputStreamSupplier supp = new CustomInputStreamSupplier(currentFile);
        scatterSample.addEntry(archiveEntry, supp);
    }

    private static void compressCurrentDirectory(File dir, CompressZip compressZip, String dirName) throws IOException {
        if (dir == null) {
            throw new IOException("源路径为空!");
        }

        String relativePath = "";
        if (dir.isFile()) {
            relativePath = dir.getName();
            addEntry(relativePath, dir, compressZip);
            return;
        }
        if (dir.listFiles() == null) {
            return;
        }
        // 空文件夹
        if (dir.listFiles().length == 0) {
            relativePath = dirName + dir.getAbsolutePath().replace(compressZip.getRootPath(), "");
            addEntry(relativePath + File.separator, dir, compressZip);
            return;
        }
        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                compressCurrentDirectory(f, compressZip, dirName);
            } else {
                relativePath = dirName + f.getParent().replace(compressZip.getRootPath(), "");
                addEntry(relativePath + File.separator + f.getName(), f, compressZip);
            }
        }
    }

    /**
     * 压缩文件方法
     * @param directoryPath 需要打包的文件或文件夹名称
     * @param zipPath 压缩包的路径 + 压缩包的包名(f:/xx.zip or /usr/loacl/xx.zip)
     * @throws Exception
     * @return 耗时 ms
     */
    public static long compressFiles2Zip(final String directoryPath, final String zipPath) {
        long begin = System.currentTimeMillis();
        ZipArchiveOutputStream zipArchiveOutputStream = null;
        try {
            File zipFile = new File(zipPath);
            File dstFolder = new File(zipFile.getParent());
            if (!dstFolder.isDirectory()) {
                dstFolder.mkdirs();
            }
            File rootDir = new File(directoryPath);
            final CompressZip compressZip = new CompressZip(rootDir.getAbsolutePath());
            compressCurrentDirectory(rootDir, compressZip, rootDir.getName());
            zipArchiveOutputStream = new ZipArchiveOutputStream(zipFile);
            compressZip.writeTo(zipArchiveOutputStream);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (zipArchiveOutputStream != null) {
                try {
                    zipArchiveOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("压缩用时:" + (end - begin) + " ms");
        return end - begin;
    }

    /**
     * zip压缩包解压成文件到指定文件夹
     * @param zipFilePath   要解压的文件
     * @param targetDirPath 解压的目的路径
     * @return 耗时 ms
     */
    public static long decompressZip2Files(String zipFilePath, String targetDirPath) {
        long begin = System.currentTimeMillis();
        InputStream inputStream = null;
        OutputStream outputStream = null;
        //zip文件输入流
        ZipArchiveInputStream zipArchiveInputStream = null;
        ArchiveEntry archiveEntry = null;
        try {
            File zipFile = new File(zipFilePath);
            inputStream = new FileInputStream(zipFile);
            zipArchiveInputStream = new ZipArchiveInputStream(inputStream, "UTF-8");

            while (null != (archiveEntry = zipArchiveInputStream.getNextEntry())) {
                //获取文件名
                String archiveEntryFileName = archiveEntry.getName();
                //构造解压后文件的存放路径
                String archiveEntryPath = targetDirPath + File.separator +archiveEntryFileName;
                //把解压出来的文件写到指定路径
                File entryFile = new File(archiveEntryPath);
                if (!entryFile.exists()) {
                    boolean mkdirs = entryFile.getParentFile().mkdirs();

                }
                byte[] buffer = new byte[1024 * 5];
                outputStream = new FileOutputStream(entryFile);
                int len = -1;
                while ((len = zipArchiveInputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }
                outputStream.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
                if (null != outputStream) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (null != zipArchiveInputStream) {
                    try {
                        zipArchiveInputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (null != inputStream) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
        }
        long end = System.currentTimeMillis();
        System.out.println("解压缩用时:" + (end - begin) + " ms");
        return end - begin;
    }

}
public class TestZipFileUtil {

    public static void main(String[] arg) throws Exception {

        /**
         * 压缩
         */
        ZipFileUtil.compressFiles2Zip("F:/1.png", "f:/1.zip");


        /**
         * 解压缩
         */
        //ZipFileUtil.decompressZip2Files("F:\\myzip\\test\\1.zip", "f:\\my\\");
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!