Inconsistency between ZipEntry size for ZipInputStream and JarInputStream
Asked Answered
P

3

5

I have bunch of image files in a zip file which I am reading using ZipInputStream and Iterating over ZipEntry from an Applet.

   ZipInputStream zis = new ZipInputStream(in);
        ZipEntry ze = null;
        while ((ze = zis.getNextEntry()) != null) {
            htSizes.put(ze.getName(), new Integer((int) ze.getSize()));
            if (ze.isDirectory()) {
                continue;
            }
            int size = (int) ze.getSize();
            // -1 means unknown size.
            if (size == -1) {
                size = ((Integer) htSizes.get(ze.getName())).intValue();
            }
            byte[] b = new byte[(int) size];
            int rb = 0;
            int chunk = 0;
            while (((int) size - rb) > 0) {
                chunk = zis.read(b, rb, (int) size - rb);
                if (chunk == -1) {
                    break;
                }
                rb += chunk;
            }
            // add to internal resource hashtable
            htJarContents.put(ze.getName(), b);
        }

However when I put these images into a signed jar "ze.getSize()" is coming as -1, and image file is getting read incorrectly.

Can someone help me in this regards.

Peek answered 23/1, 2012 at 13:54 Comment(3)
You really shouldn't be truncating the size down to an int. Also, see @JonSkeet's answer below.Fafnir
possible duplicate of JarEntry.getSize() is returning -1 when the jar files is opened as InputStream from URLCain
Why not just get the input stream of the compressed image and pass it to ImageIO.read(InputStream)?Simonette
I
5

Yes, -1 means the size is unknown - it's not clear why you're putting it into a map and then fetching it out again though..

Basically, if the size is unknown you should keep reading buffers until read returns -1. One simply way is to create a ByteArrayOutputStream, and keep copying from the ZipEntry to that - then once you've finished reading, just get the byte array from the ByteArrayOutputStream. It will handle any resizing necessary.

Intracranial answered 23/1, 2012 at 13:59 Comment(0)
C
2

This question is similar to JarEntry.getSize() is returning -1 when the jar files is opened as InputStream from URL and the answer is the same.

The javadoc specifically states that that method returns -1 if the size cannot be determined. And (according to Tom Hawtin) it is also possible that the size returned is non-negative ... and incorrect.

The bottom line is that you need to treat the reported size as a hint only, and read the entire stream into and expandable byte buffer (e.g. a ByteArrayOutputStream).

Cain answered 23/1, 2012 at 14:3 Comment(0)
D
2

getSize() returns the uncompressed size of the entry’s data, or -1 when not known.

So if the size returned is negative, add it to 0xffffffffl to get the correct value.

Example:

long size = ze.getSize();
if (size < 0) {
    size = 0xffffffffl + size ;
}

Reference: Negative value returned for ZipEntry.getSize()

Delegation answered 3/8, 2013 at 3:57 Comment(1)
Just as a note, the OP is getting -1 back from getSize and not a large negative number caused by an int overflow. The bug referenced in your post was also fixed in java 6 update 18.Maggoty

© 2022 - 2024 — McMap. All rights reserved.