Search code examples
javainputstreamunzip

ZipInputStream doesn't report *actual* (i.e. compressed) bytes read


Love this website! My issue is as follows:

I'm reading a zip file that's coming over a network from an HTTP "PUT" request. The request header tells me that the Content-Length is (say) 1Mb. The following code creates the ZipInputStream, and saves the zip contents to files in the current directory:

ZipInputStream zis = new ZipInputStream(inputStream);
ZipEntry ze;
long totalBytesRead = 0;
while ((ze = zis.getNextEntry()) != null) {
    BufferedOutputStream outStream = new BufferedOutputStream(new FileOutputStream(ze.getName()));
    byte[] buffer = new byte[4096];
    int i;
    while ((i = zis.read(buffer)) != -1) {
        totalBytesRead+=i;
        outStream.write(buffer,0,i);
    } 
    outStream.close();
}
inputStream.close();

When all is said and done, totalBytesRead is equal to about 1.5Mb (depending on compression of the files, could be anything though!). What I'd like to know is if there is a way to find out how many actual bytes have been read from the original inputStream? Both ze.getSize() and ze.getCompressedSize() return -1 for every zipped entry (i.e. it doesn't know). I need this info for a progress bar to show how many bytes of the transmitted zip file have been read off the network.

Suggestions? Should I perhaps subclass ZipInputStream and try to find out how many bytes it's reading from it's wrapped InputStream?

Thanks in advance!


Solution

  • Sure, that seems reasonable.

    There are basically two options: read all the bytes, store them (in memory or a file), count them, then decompress them; or count them as they come in. The former seems inefficient, and the latter will require a subclass of InputStream which has the ability to count the bytes it reads. I can't think of one in the standard library, but implementations probably exist out there - then again it'd be pretty easy to write your own.