博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 高效压缩zip
阅读量:7188 次
发布时间:2019-06-29

本文共 5825 字,大约阅读时间需要 19 分钟。

以前遇到文件压缩的功能是都直接从网上找一个,随便测试一下能用就行了。既不关心效率也没有好好的测一下是否支持内嵌文件夹的压缩。

现在仔细测试才发现网上好多都不支持内嵌文件夹的压缩。 支持的不是有问题就是速度比较慢。

框架里jar包里的类诸如IOUtils,FileUtils里没有提供压缩的方法。连commons-compress.jar里都没有现成的。

我决定自己写一个。真写的时候发现不是那么容易。目标是 给定一个文件夹路径和一个输出路径,将给定文件夹里的所有东西都压缩到zip里。

在commons-compress的文档里发现有一个支持多线程压缩的类 ParallelScatterZipCreator。我决定试一试。

在github里找到   和   这两个类。这个demo不支持带文件夹的压缩。 文档里也没有给出带文件夹压缩的demo。没办法只能仔细阅

读这个demo从api里找线索了。

仔细摸索后,代码如下:

package test;import java.io.File;import java.io.IOException;import java.util.concurrent.ExecutionException;import org.apache.commons.compress.archivers.zip.ParallelScatterZipCreator;import org.apache.commons.compress.archivers.zip.ScatterZipOutputStream;import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;import org.apache.commons.compress.archivers.zip.ZipArchiveEntryRequest;import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;import org.apache.commons.compress.parallel.InputStreamSupplier;public class ScatterSample {    private String rootPath;    ParallelScatterZipCreator scatterZipCreator = new ParallelScatterZipCreator();    // ParallelScatterZipCreator api says:    // 注意这个类不保证写入到输出文件的顺序。需要保持特定顺序的(manifests,文件夹)必须使用这个类的客户类进行处理    // 通常的做法是 在调用这个类的writeTo方法前把这些东西写入到ZipArchiveOutputStream    ScatterZipOutputStream dirs = ScatterZipOutputStream            .fileBased(File.createTempFile("whatever-preffix", ".whatever"));    public ScatterSample(String rootPath) throws IOException {        this.rootPath = rootPath;    }    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;    }}

package test;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.util.zip.ZipEntry;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 org.junit.Test;public class ScatterSampleTest {    @Test    public void testSample() throws Exception {        long begin = System.currentTimeMillis();        final File result = new File("d:/test2/eclipse2.zip");        createZipFile("F:/Java/eclipseplusUIx64_best", result);        long end = System.currentTimeMillis();        System.out.println("用时:" + (end - begin) + " ms");    }    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 void addEntry(String entryName, File currentFile, ScatterSample scatterSample) throws IOException {        ZipArchiveEntry archiveEntry = new ZipArchiveEntry(entryName);        archiveEntry.setMethod(ZipEntry.DEFLATED);        final InputStreamSupplier supp = new CustomInputStreamSupplier(currentFile);        scatterSample.addEntry(archiveEntry, supp);    }    private void compressCurrentDirectory(File dir, ScatterSample scatterSample) throws IOException {        if (dir == null) {            throw new IOException("源路径不能为空!");        }        String relativePath = "";        if (dir.isFile()) {            relativePath = dir.getName();            addEntry(relativePath, dir, scatterSample);            return;        }        // 空文件夹        if (dir.listFiles().length == 0) {            relativePath = dir.getAbsolutePath().replace(scatterSample.getRootPath(), "");            addEntry(relativePath + File.separator, dir, scatterSample);            return;        }        for (File f : dir.listFiles()) {            if (f.isDirectory()) {                compressCurrentDirectory(f, scatterSample);            } else {                relativePath = f.getParent().replace(scatterSample.getRootPath(), "");                addEntry(relativePath + File.separator + f.getName(), f, scatterSample);            }        }    }    private void createZipFile(final String rootPath, final File result) throws Exception {        File dstFolder = new File(result.getParent());        if (!dstFolder.isDirectory()) {            dstFolder.mkdirs();        }        File rootDir = new File(rootPath);        final ScatterSample scatterSample = new ScatterSample(rootDir.getAbsolutePath());        compressCurrentDirectory(rootDir, scatterSample);        final ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(result);        scatterSample.writeTo(zipArchiveOutputStream);        zipArchiveOutputStream.close();    }}
以解压后的eclipse文件为例,用时:4624 ms。比较了一下网上其他的方法,快了2倍多。这结果还算满意。 代码水平有限,只能到这儿了。如果有更精简的代码,欢迎指教。

转载地址:http://gkfkm.baihongyu.com/

你可能感兴趣的文章
遇到502错误,invalid request block size 解决方法
查看>>
Js操作Select大全(取值、设置选中等等)
查看>>
windows下架设SVN服务器并设置开机启动
查看>>
JS中typeof的用法
查看>>
投影矩阵
查看>>
微软职位内部推荐-Senior Software Engineer II-Search
查看>>
如何使用JCONSOLE 监控eclipse的tomcat
查看>>
SpringBoot+Maven多模块项目(创建、依赖、打包可执行jar包部署测试)完整流程
查看>>
Caused by: java.sql.SQLException: Field 'id' doesn't have a default value
查看>>
gitHub上如何设置或者取消电子邮箱提醒
查看>>
VC++2005快速构建安全的应用程序
查看>>
js startWith
查看>>
【Charpter 2】硬币游戏——代码分析与改进
查看>>
利用gulp 插件gulp.spritesmith 完成小图合成精灵图,并自动输出样式文件
查看>>
莫等闲,白了少年头,空悲切!
查看>>
常用SQL整理
查看>>
Node.js笔记 - 安装express
查看>>
zuul忽略表达式
查看>>
hybris安装B2B
查看>>
boot中 Quartz注入spring管理类失败
查看>>