Octavia Togami
Octavia Togami

Reputation: 4316

Does a ZipEntry persist after a ZipFile is closed?

I currently have a plausible resource leak in my library due to the fact that I hold a ZipFile open so that the returned InputStream for a certain ZipEntry is not closed. However, closing the returned InputStream doesn't close the rest of the ZipFile, so I'm stuck with it left open. Is there a way to safely close the ZipFile and keep the InputStream for returning?

Upvotes: 6

Views: 2831

Answers (1)

Kong
Kong

Reputation: 9576

Here's the implementation of 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();

Notice the call to #ensureOpenOrZipException.

So the answer to your question is unfortunately no, there is no way to keep the stream open.

What you could do instead is wrap and hook the #close on the InputStream to close your zip file:

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

Another approach would be to buffer it:

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

Obviously this has now all gone into memory, so your data will need to be a reasonable size.

Upvotes: 6

Related Questions