私はJDKとApacheの圧縮ライブラリに同梱されているデフォルトのZipライブラリを調べましたが、3つの理由でそれらには不満があります。
それらは肥大化しており、悪い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)はマイナーな点ですが、私は本当に1行のインターフェースを持つよくテストされたライブラリーが欲しいのです。
私はその遅れを知っています、そしてたくさんの答えがありますが、これ Zip4j は私が使ったことがある圧縮のための最も良いライブラリの1つです。その単純な(ボイラーコードなし)そしてパスワードで保護されたファイルを簡単に扱うことができます。
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 's 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
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();
}
}
}
あなたがチェックアウトすることができるもう一つの選択肢はMaven Centralとプロジェクトページから入手可能なzt-Zipです https://github.com/zeroturnaround]/zt-Zip
それは標準のパッキングとアンパック機能(ストリームとファイルシステム)+アーカイブのファイルをテストするかエントリを追加/削除するたくさんのヘルパーメソッドを持っています。
プロジェクトビルドパスに ここ と 追加 から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);
}/**/
}
とてもいいプロジェクトは TrueZip です。
TrueZIPは、仮想ファイルシステム(VFS)用のJavaベースのプラグインフレームワークで、あたかも単なるディレクトリであるかのようにアーカイブファイルへの透過的なアクセスを提供します。
例えば( Webサイト から):
File file = new TFile("archive.tar.gz/README.TXT");
OutputStream out = new TFileOutputStream(file);
try {
// Write archive entry contents here.
...
} finally {
out.close();
}
別のオプションは JZlib です。私の経験では、Zip4Jほど「ファイル中心」ではありません。そのため、ファイルではなくメモリ内BLOBを扱う必要がある場合は、それを検討してください。
再帰的にファイルを解凍および解凍するための完全な例がここにあります。 http://developer-tips.hubpages.com/hub/Zipping-and-Unzipping-Nested-Directories-in-Java-using-Apache-Commons-圧縮
http://commons.Apache.org/vfs/ を見ましたか?それはあなたのために多くのことを単純化すると主張しています。しかし、私はこれをプロジェクトで使ったことは一度もありません。
私はまた、JDKやApache Compression以外のJavaネイティブ圧縮ライブラリについては知りません。
私たちが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();
}