使用Java ZipOutputStream和BufferedOutputStream的首选方法

jja*_*man 54 java io outputstream

在Java中,我首先实例化ZipOutputStream还是首先实例化BufferedOutputStream?例:

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

// use zip output stream to write to
Run Code Online (Sandbox Code Playgroud)

要么:

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

// use buffered stream to write to
Run Code Online (Sandbox Code Playgroud)

在我非科学的时间里,我似乎无法在这里说出很多不同之处.我在Java API中看不到任何表明这些方法之一是必要的还是首选的.有什么建议?似乎首先压缩输出然后缓冲它以进行写入会更有效.

Dan*_*yes 81

你应该总是BufferedOutputStreamZipOutputStream,而不是相反.请参阅以下代码:

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();
}
Run Code Online (Sandbox Code Playgroud)

正如评论所说,putNextEntry()closeEntry()方法不可用BufferedOutputStream.不调用这些方法ZipOutputStream会抛出异常java.util.zip.ZipException: no current ZIP entry.

为了完整起见,值得注意的是,最后子句只要求close()ZipOutputStream.这是因为按照惯例,所有内置Java输出流包装器实现都会传播关闭.

编辑

我只是反过来测试它.事实证明,一个包裹ZipOutputStreamBufferedOutputStream,然后只调用write()就可以了(不创建/关闭的条目)不会抛出ZipException.相反,生成的ZIP文件将损坏,其中没有任何条目.

  • 在那种情况下,是否有任何缓冲感?我不是在这里争论,只是好奇,如果有人检查,到目前为止. (3认同)
  • 正如您在[MrSmith42's](http://stackoverflow.com/a/14462420/244935)的第一部分中看到的那样,使用内部BufferedOutputStream可能有潜在的好处,方法是在写入磁盘之前先缓冲已压缩的输出流。您将使用更多的内存(用于在刷新到磁盘之前将zip压缩的字节保留在内存缓冲区中),但是效率更高,因为磁盘I / O以更大的字节块(BufferedOutputStream初始化的缓冲区大小)完成与)。 (3认同)

MrS*_*h42 22

你应该:

ZipOutputStream out =  new ZipOutputStream(new BufferedOutputStream(dest));
Run Code Online (Sandbox Code Playgroud)

因为你想缓冲写入光盘(因为这在大数据块中比在许多小块中更有效).


这个

new BufferedOutputStream(new ZipOutputStream(dest));
Run Code Online (Sandbox Code Playgroud)

在压缩之前会缓冲.但这一切都发生在内存中并且不需要缓冲,因为很多小内存访问速度与几个大内存访问速度大致相同.在存储器中,所需的时间与读/写的字节数成正比.

如评论中所述:

其方法ZipOutputStream不属于其中的部分BufferedOutputStream也不可用.例如putNextEntrycloseEntry.

  • 我的观点是,没有比较两者之间任何表现的意义.将`ZipOutputStream`包装在`BufferedOutputStream`中完全没有意义,因为它不公开`putNextEntry`和`closeEntry`方法. (6认同)
  • 作为答案的向下投票没有提到ZipOutputStream的方法在流上时不可用的事实,如果包装错误的方式. (2认同)