How would I properly zip bytes to a ByteArrayOutputStream
and then read that using a ByteArrayInputStream
? I have the following method:
private byte[] getZippedBytes(final String fileName, final byte[] input) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ZipOutputStream zipOut = new ZipOutputStream(bos);
ZipEntry entry = new ZipEntry(fileName);
entry.setSize(input.length);
zipOut.putNextEntry(entry);
zipOut.write(input, 0, input.length);
zipOut.closeEntry();
zipOut.close();
//Turn right around and unzip what we just zipped
ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(bos.toByteArray()));
while((entry = zipIn.getNextEntry()) != null) {
assert entry.getSize() >= 0;
}
return bos.toByteArray();
}
When I execute this code, the assertion at the bottom fails because entry.size
is -1
. I don't understand why the extracted entity doesn't match the entity that was zipped.
Why is the size -1?
Calling
getNextEntry
in aZipInputStream
just position the read cursor at start of the entry to read.The size (along with other metadata) is stored at the end of the actual data, therefore is not readily available when the cursor is positioned at the start.
These information becomes available only after you read the whole entry data or just go to the next entry.
For example, going to the next entry:
or reading the whole entry data:
Your misunderstanding is quite common and there are a number of bug reports regarding this problem (which are closed as "Not an Issue"), like JDK-4079029, JDK-4113731, JDK-6491622.
As also mentioned in the bug reports, you could use
ZipFile
instead ofZipInputStream
which would allow to reach the size information prior to access the entry data; but to create aZipFile
you need aFile
(see the constructors) instead of a byte array.For example:
How to get the data from the input stream?
If you want to check if the unzipped data is equal to the original input data, you could read from the input stream like so:
Now
output
should have the same content asinput
.