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?
Asked
Active
Viewed 2,511 times
1 Answers
6
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.

Kong
- 8,792
- 15
- 68
- 98
-
Why's it a hack? It's a simple encapsulation of the zip #close. I added another approach that was my first thought, but it uses a memory buffer, which might not work for you. – Kong Jun 17 '14 at 23:41
-
Actually looking at the code, I realized that `getInputStream` returns just an InputStream, I thought it was more specific. It's not a hack then! – Octavia Togami Jun 18 '14 at 01:13
-
Polymorphism to the rescue! – Kong Jun 18 '14 at 01:40
-
And make sure to wrap your InputSteam with BufferedInputStream. Single byte #read calls perform horribly on the JDK's zip input streams. – Kong Jun 18 '14 at 01:44
-
Since it's a library I can't ensure the wrapping unless I do it on my side, but I think it's safe to assume that most people will convert to `BufferedInputStream`. (Even if they don't, they'd want to be opening a ZipFile and not a regular File). – Octavia Togami Jun 18 '14 at 02:27