web-dev-qa-db-ja.com

ファイルをZip / unzipするための優れたJavaライブラリは何ですか?

私はJDKとApacheの圧縮ライブラリに同梱されているデフォルトのZipライブラリを調べましたが、3つの理由でそれらには不満があります。

  1. それらは肥大化しており、悪いAPI設計をしています。 50行のボイラープレートバイト配列出力、Zip入力、ストリームをファイルして関連ストリームをクローズし、例外をキャッチしてバイトバッファを自分で移動する ?なぜZipper.unzip(InputStream zipFile, File targetDirectory, String password = null)Zipper.Zip(File targetDirectory, String password = null)のような単純なAPIがうまく動かないのですか?

  2. 解凍するとファイルのメタデータが破壊され、パスワード処理が壊れます。

  3. また、私が試したすべてのライブラリは、UNIXで入手できるコマンドラインのZipツールと比較して2〜3倍低速でしたか。

私にとって(2)と(3)はマイナーな点ですが、私は本当に1行のインターフェースを持つよくテストされたライブラリーが欲しいのです。

209
pathikrit

私はその遅れを知っています、そしてたくさんの答えがありますが、これ 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>
272
user2003470

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

68

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();
        }
    }
}
32

あなたがチェックアウトすることができるもう一つの選択肢はMaven Centralとプロジェクトページから入手可能なzt-Zipです https://github.com/zeroturnaround]/zt-Zip

それは標準のパッキングとアンパック機能(ストリームとファイルシステム)+アーカイブのファイルをテストするかエントリを追加/削除するたくさんのヘルパーメソッドを持っています。

22
toomasr

Zip4j でフォルダ/ファイルをZip/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);
    }/**/
}
14
Minhas Kamal

とてもいいプロジェクトは 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();
}
7
Michael

別のオプションは JZlib です。私の経験では、Zip4Jほど「ファイル中心」ではありません。そのため、ファイルではなくメモリ内BLOBを扱う必要がある場合は、それを検討してください。

再帰的にファイルを解凍および解凍するための完全な例がここにあります。 http://developer-tips.hubpages.com/hub/Zipping-and-Unzipping-Nested-Directories-in-Java-using-Apache-Commons-圧縮

0
user1491819

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();
}
0
wemu