Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 253
Octavia Togami Avatar asked Jun 17 '14 22:06

Octavia Togami


People also ask

How do I close ZipInputStream?

ZipInputStream. close() method closes this input stream and releases any system resources associated with the stream.

How do you read the contents of ZipEntry?

extends ZipEntry> entries = zipFile. entries(); Each entry is of type ZipEntry which provides the following methods for reading information of an individual entry (to name a few): getName(): returns the name of the entry in form of a relative path.

How do I get files from ZipEntry?

Getting a ZipEntry ZipEntry ). To extract a file from the ZIP file you can call the method getEntry() method on the ZipFile class. Here is an example of calling getEntry() : ZipEntry zipEntry = zipFile.

Can Java open ZIP files?

To unzip a zip file, we need to read the zip file with ZipInputStream and then read all the ZipEntry one by one. Then use FileOutputStream to write them to file system. We also need to create the output directory if it doesn't exists and any nested directories present in the zip file.


1 Answers

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.

like image 129
Kong Avatar answered Sep 23 '22 02:09

Kong