java 压缩_Java 高效压缩zip

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

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

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

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

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

在github里找到 ScatterSample.java  和  ScatterSampleTest.java 这两个类。这个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倍多。这结果还算满意。 代码水平有限,只能到这儿了。如果有更精简的代码,欢迎指教。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值