ZipFile 关闭后 ZipEntry 是不是仍然存在?

Posted

技术标签:

【中文标题】ZipFile 关闭后 ZipEntry 是不是仍然存在?【英文标题】:Does a ZipEntry persist after a ZipFile is closed?ZipFile 关闭后 ZipEntry 是否仍然存在? 【发布时间】:2014-06-17 22:37:24 【问题描述】:

我的库中目前有一个看似合理的资源泄漏,因为我打开了一个 ZipFile,因此某个 ZipEntry 的返回 InputStream 没有关闭。但是,关闭返回的 InputStream 并不会关闭 ZipFile 的其余部分,所以我坚持让它保持打开状态。有没有办法安全地关闭 ZipFile 并保留 InputStream 以供返回?

【问题讨论】:

【参考方案1】:

这里是InputStream from ZipFile的实现:

/*
* Inner class implementing the input stream used to read a
* (possibly compressed) zip file entry.
*/
private class ZipFileInputStream extends InputStream 

   ...

   public int read(byte b[], int off, int len) throws IOException 
       if (rem == 0) 
           return -1;
       
       if (len <= 0) 
           return 0;
       
       if (len > rem) 
           len = (int) rem;
       
       synchronized (ZipFile.this) 
           ensureOpenOrZipException();

注意对#ensureOpenOrZipException的调用。

所以很遗憾,您的问题的答案是否定的,没有办法保持流打开。

您可以做的是包装并挂钩 InputStream 上的 #close 以关闭您的 zip 文件:

InputStream zipInputStream = ...
return new InputStream() 
    @Override
    public int read() throws IOException 
        return zipInputStream.read();
    
    @Override
    public void close() throws IOException 
        zipInputStream.close();
        zipFile.close();
    

另一种方法是缓冲它:

InputStream myZipInputStream = ...
//Read the zip input stream fully into memory
byte[] buffer = ByteStreams.toByteArray(zipInputStream);
zipFile.close();
return new ByteArrayInputStream(buffer);

显然,这一切现在都已进入内存,因此您的数据需要有一个合理的大小。

【讨论】:

为什么是 hack?这是 zip #close 的简单封装。我添加了另一种我最初想到的方法,但它使用了内存缓冲区,这可能不适合你。 实际看代码,发现getInputStream返回的只是一个InputStream,我还以为是更具体的。那么这不是黑客攻击! 多态的救援! 并确保使用 BufferedInputStream 包装您的 InputSteam。单字节 #read 调用在 JDK 的 zip 输入流上执行得非常糟糕。 因为它是一个库,除非我自己做,否则我无法确保包装,但我认为可以肯定地假设大多数人会转换为BufferedInputStream。 (即使他们不这样做,他们也希望打开 ZipFile 而不是常规文件)。

以上是关于ZipFile 关闭后 ZipEntry 是不是仍然存在?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ZipEntry 创建输入流

如何在不写入输出流的情况下从 ZipInputStream 获取每个 ZipFile 条目的字节/内容?

如何访问 ZipEntry 内的文件夹内的文件

java用apache的ZipEntry压缩文件名为中文的word文件时,文件名乱码

matplotlib 是不是仍在维护[关闭]

从函数返回后文件会关闭吗?