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

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

【问题讨论】:

    标签: java inputstream zipfile


    【解决方案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 而不是常规文件)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    • 2013-04-24
    • 2022-11-21
    • 1970-01-01
    • 2020-01-16
    • 2014-05-07
    相关资源
    最近更新 更多