web-dev-qa-db-ja.com

推奨される使用方法Java ZipOutputStreamおよびBufferedOutputStream

In Java最初に ZipOutputStream をインスタンス化するか、最初に BufferedOutputStream をインスタンス化するかは問題になりますか?例:

FileOutputStream dest = new FileOutputStream(file);
ZipOutputStream Zip = new ZipOutputStream(new BufferedOutputStream(dest));

// use Zip output stream to write to

または:

FileOutputStream dest = new FileOutputStream(file);
BufferedOutputStream out = new BufferedOutputStream(new ZipOutputStream(dest));

// use buffered stream to write to

私の非科学的なタイミングでは、ここで多くの違いを伝えることはできないようです。 Javaこれらの方法のいずれかが必要または優先されるかどうかを示すAPIには何も表示されません。アドバイスはありますか?最初に出力を圧縮し、次に書き込みのためにバッファリングする方が良いようです効率的。

52
jjathman

BufferedOutputStreamは常にZipOutputStreamでラップする必要があります。以下のコードを参照してください。

_FileOutputStream fos = new FileOutputStream("hello-world.Zip");
BufferedOutputStream bos = new BufferedOutputStream(fos);
ZipOutputStream zos = new ZipOutputStream(bos);

try {
    for (int i = 0; i < 10; i++) {
        // not available on BufferedOutputStream
        zos.putNextEntry(new ZipEntry("hello-world." + i + ".txt"));
        zos.write("Hello World!".getBytes());
        // not available on BufferedOutputStream
        zos.closeEntry();
    }
}
finally {
    zos.close();
}
_

コメントにあるように、putNextEntry()およびcloseEntry()メソッドはBufferedOutputStreamでは使用できません。これらのメソッドを呼び出すことなく、ZipOutputStreamは例外_Java.util.Zip.ZipException: no current Zip entry_をスローします。

完全を期すために、finally節はZipOutputStreamでのみclose()を呼び出すことに注意してください。これは、慣例により、すべての組み込みJava出力ストリームラッパーの実装がクローズを伝播するためです。

編集

私はそれを別の方法でテストしました。 ZipOutputStreamBufferedOutputStreamでラップし、その上でwrite()を呼び出すだけで(エントリを作成/終了せずに)ZipExceptionをスローしないことがわかります。代わりに、結果のZipファイルが破損し、その中にエントリがありません。

78
Daniel Dinnyes

あなたがすべき:

ZipOutputStream out =  new ZipOutputStream(new BufferedOutputStream(dest));

ディスクへの書き込みをバッファリングするためです(これは、多くの小さなデータブロックよりもビッグデータブロックではるかに効率的であるためです)。


この

new BufferedOutputStream(new ZipOutputStream(dest));

zip圧縮の前にバッファリングします。しかし、これはすべてメモリで行われ、バッファリングを必要としません。これは、多くの小さなメモリアクセスがいくつかの大きなメモリアクセスとほぼ同じ速度だからです。一般的なメモリでは、必要な時間は読み取り/書き込みバイト数に比例します。

コメントで述べたように:

ZipOutputStreamの一部ではないBufferedOutputStreamのメソッドも利用できません。例えば。 putNextEntryおよびcloseEntry

21
MrSmith42