压缩 - 压缩/解压缩文件的优秀Java库是什么?
我查看了JDK和Apache压缩库附带的默认Zip库,我对它们不满意有三个原因:
它们很臃肿,API设计不好。 我必须写50行锅炉板字节数组输出,zip输入,文件输出流和关闭相关流并捕获异常并自行移动字节缓冲区? 为什么我不能拥有一个看起来像Zipper.unzip(InputStream zipFile, File targetDirectory, String password = null)和Zipper.zip(File targetDirectory, String password = null)的简单API?
它似乎压缩解压缩破坏文件元数据和密码处理被打破。
此外,与我使用UNIX获得的命令行zip工具相比,我尝试的所有库都慢2-3倍?
对我来说(2)和(3)是次要的,但我真的想要一个带有单线界面的良好测试库。
9个解决方案
251 votes
我知道它已经很晚了,而且有很多答案,但这个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的依赖是:
net.lingala.zip4j
zip4j
1.3.2
user2003470 answered 2019-03-15T12:02:18Z
58 votes
使用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();
}
它仍然是一些样板代码,但它只有1个非外来依赖:Commons-IO
Geoffrey De Smet answered 2019-03-15T12:02:51Z
26 votes
仅使用JDK提取zip文件及其所有子文件夹:
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();
}
}
}
Bashir Beikzadeh answered 2019-03-15T12:03:23Z
20 votes
您可以查看的另一个选项是来自Maven中心的zt-zip和项目页面[https://github.com/zeroturnaround/zt-zip]
它具有标准的打包和解包功能(在流和文件系统上)+许多帮助方法来测试存档中的文件或添加/删除条目。
toomasr answered 2019-03-15T12:03:58Z
12 votes
使用zip4j压缩/解压缩文件夹/文件的完整实现
从此处下载jar,并将其添加到项目构建路径中。 下面的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);
}/**/
}
Minhas Kamal answered 2019-03-15T12:04:33Z
7 votes
一个非常好的项目是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();
}
Michael answered 2019-03-15T12:05:15Z
2 votes
另一种选择是JZlib。 根据我的经验,它不像zip4J那样“以文件为中心”,所以如果你需要处理内存中的blob而不是文件,你可能想看看它。
Henrik Aasted Sørensen answered 2019-03-15T12:05:50Z
0 votes
这里有一个完整的示例,用于递归地压缩和解压缩文件:[http://developer-tips.hubpages.com/hub/Zipping-and-Unzipping-Nested-Directories-in-Java-using-Apache-Commons-Compress]
user1491819 answered 2019-03-15T12:06:29Z
0 votes
你看过[http://commons.apache.org/vfs/]了吗? 它声称为您简化了很多事情。 但我从未在项目中使用它。
我也不了解除JDK或Apache Compression之外的Java-Native压缩库。
我记得有一次我们从Apache Ant中删除了一些功能 - 他们有很多内置的压缩/解压缩功能。
使用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();
}
wemu answered 2019-03-15T12:07:31Z