什么是一个好的Java库来压缩/解压缩文件?

我查看了JDK和Apache压缩库附带的默认Zip库,我不满意这三个原因:

  1. 他们臃肿,糟糕的APIdevise。 我必须写50行的锅炉板字节数组输出,zipinput,文件输出stream和closures相关的stream,并捕捉exception和我自己的字节缓冲区 ? 为什么我不能有一个看起来像这样的Zipper.unzip(InputStream zipFile, File targetDirectory, String password = null)Zipper.zip(File targetDirectory, String password = null)的简单API?

  2. 它似乎压缩解压缩文件元数据和密码处理破坏。

  3. 另外,与我用UNIX获得的命令行压缩工具相比,我尝试的所有库都慢了2-3倍?

对我来说(2)和(3)是次要的,但我真的想要一个单线接口的好的testing库。

我知道它晚了,有很多答案,但这个zip4j是我用过的最好的压缩库之一。 它简单(没有锅炉代码),可以轻松处理密码保护的文件。

 import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.core.ZipFile; public static void unzip(){ String source = "some/compressed/file.zip"; String destination = "some/destination/folder"; String password = "password"; try { ZipFile zipFile = new ZipFile(source); if (zipFile.isEncrypted()) { zipFile.setPassword(password); } zipFile.extractAll(destination); } catch (ZipException e) { e.printStackTrace(); } } 

Maven的依赖是:

 <dependency> <groupId>net.lingala.zip4j</groupId> <artifactId>zip4j</artifactId> <version>1.3.2</version> </dependency> 

有了Apache Commons-IO的IOUtils你可以这样做:

 java.util.zip.ZipFile zipFile = new ZipFile(file); try { Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); File entryDestination = new File(outputDir, entry.getName()); if (entry.isDirectory()) { entryDestination.mkdirs(); } else { entryDestination.getParentFile().mkdirs(); InputStream in = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(entryDestination); IOUtils.copy(in, out); IOUtils.closeQuietly(in); out.close(); } } } finally { zipFile.close(); } 

这仍然是一些样板代码,但它只有一个非奇异的依赖: Commons-IO

解压缩zip文件及其所有子文件夹,仅使用JDK:

 private void extractFolder(String zipFile,String extractFolder) { try { int BUFFER = 2048; File file = new File(zipFile); ZipFile zip = new ZipFile(file); String newPath = extractFolder; new File(newPath).mkdir(); Enumeration zipFileEntries = zip.entries(); // Process each entry while (zipFileEntries.hasMoreElements()) { // grab a zip file entry ZipEntry entry = (ZipEntry) zipFileEntries.nextElement(); String currentEntry = entry.getName(); File destFile = new File(newPath, currentEntry); //destFile = new File(newPath, destFile.getName()); File destinationParent = destFile.getParentFile(); // create the parent directory structure if needed destinationParent.mkdirs(); if (!entry.isDirectory()) { BufferedInputStream is = new BufferedInputStream(zip .getInputStream(entry)); int currentByte; // establish buffer for writing file byte data[] = new byte[BUFFER]; // write the current file to disk FileOutputStream fos = new FileOutputStream(destFile); BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER); // read and write until last byte is encountered while ((currentByte = is.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, currentByte); } dest.flush(); dest.close(); is.close(); } } } catch (Exception e) { Log("ERROR: "+e.getMessage()); } } 

Zip文件及其所有子文件夹:

  private void addFolderToZip(File folder, ZipOutputStream zip, String baseName) throws IOException { File[] files = folder.listFiles(); for (File file : files) { if (file.isDirectory()) { addFolderToZip(file, zip, baseName); } else { String name = file.getAbsolutePath().substring(baseName.length()); ZipEntry zipEntry = new ZipEntry(name); zip.putNextEntry(zipEntry); IOUtils.copy(new FileInputStream(file), zip); zip.closeEntry(); } } } 

另外一个选项是你可以从Maven中心获得zt-zip ,在https://github.com/zeroturnaround/zt-zip

它具有标准的打包和解压缩function(在stream和文件系统上)+大量的辅助方法来testing档案中的文件或添加/删除条目。

完全实现压缩/解压缩文件/文件夹

这里我的意图是帮助新手实施


我已经使用zip4j ,正如接受的答案所示。 从这里下载jar,并将其添加到您的项目构buildpath。 下面的class可以压缩和提取任何文件或文件夹,有或没有密码保护 –

 import java.io.File; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.util.Zip4jConstants; import net.lingala.zip4j.core.ZipFile; public class Compressor { public static void zip(String targetPath, String destinationFilePath, String password) { try { ZipParameters parameters = new ZipParameters(); parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); if(password.length()>0){ parameters.setEncryptFiles(true); parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES); parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256); parameters.setPassword(password); } ZipFile zipFile = new ZipFile(destinationFilePath); File targetFile = new File(targetPath); if(targetFile.isFile()){ zipFile.addFile(targetFile, parameters); }else if(targetFile.isDirectory()){ zipFile.addFolder(targetFile, parameters); } } catch (Exception e) { e.printStackTrace(); } } public static void unzip(String targetZipFilePath, String destinationFolderPath, String password) { try { ZipFile zipFile = new ZipFile(targetZipFilePath); if (zipFile.isEncrypted()) { zipFile.setPassword(password); } zipFile.extractAll(destinationFolderPath); } catch (Exception e) { e.printStackTrace(); } } /**/ /// for test only public static void main(String[] args) { String targetPath = "target\\file\\or\\folder\\path"; String zipFilePath = "zip\\file\\Path"; String unzippedFolderPath = "destination\\folder\\path"; String password = "your_password"; // keep it EMPTY<""> for applying no password protection Compressor.zip(targetPath, zipFilePath, password); Compressor.unzip(zipFilePath, unzippedFolderPath, password); }/**/ } 

一个非常好的项目是TrueZip 。

TrueZIP是一个基于Java的虚拟文件系统(VFS)插件框架,它提供对存档文件的透明访问,就好像它们只是普通的目录

例如(来自网站 ):

 File file = new TFile("archive.tar.gz/README.TXT"); OutputStream out = new TFileOutputStream(file); try { // Write archive entry contents here. ... } finally { out.close(); } 

另一个select是JZlib 。 根据我的经验,它比zip4J更less“以文件为中心”,所以如果您需要处理内存中的斑点而不是文件,那么您可能需要查看它。

这里有一个完整的例子来recursion压缩和解压缩文件: http : //developer-tips.hubpages.com/hub/Zipping-and-Unzipping-Nested-Directories-in-Java-using-Apache-Commons-Compress

你有没有看看http://commons.apache.org/vfs/ ? 它声称为你简化了很多事情。 但是我从来没有用过这个项目。

我也不知道JDK或Apache压缩以外的Java-Native压缩库。

我记得有一次,我们从Apache Ant中剥离了一些function – 他们有很多的内置压缩/解压缩的工具。

使用VFS的示例代码如下所示:

 File zipFile = ...; File outputDir = ...; FileSystemManager fsm = VFS.getManager(); URI zip = zipFile.toURI(); FileObject packFileObject = fsm.resolveFile(packLocation.toString()); FileObject to = fsm.toFileObject(destDir); FileObject zipFS; try { zipFS = fsm.createFileSystem(packFileObject); fsm.toFileObject(outputDir).copyFrom(zipFS, new AllFileSelector()); } finally { zipFS.close(); }