For good or bad I have been using code like the following without any problems:
ZipFile aZipFile = new ZipFile(fileName);
InputStream zipInput = aZipFile.getInputStream(name);
int theSize = zipInput.available();
byte[] content = new byte[theSize];
zipInput.read(content, 0, theSize);
I have used it (this logic of obtaining the available size and reading directly to a byte buffer)
for File
I/O without any issues and I used it with zip files as well.
But recently I stepped into a case that the zipInput.read(content, 0, theSize);
actually reads 3 bytes less that the theSize
available.
And since the code is not in a loop to check the length returned by zipInput.read(content, 0, theSize);
I read the file with the 3 last bytes missing
and later the program can not function properly (the file is a binary file).
Strange enough with different zip files of larger size e.g. 1075 bytes (in my case the problematic zip entry is 867 bytes) the code works fine!
I understand that the logic of the code is probably not the "best" but why am I suddenly getting this problem now?
And how come if I run the program immediately with a larger zip entry it works?
Any input is highly welcome
Thanks
The best way to do this should be as bellows:
where the IOUtils.toByteArray(in) method keeps reading until EOF and then return the byte array.
From the
InputStream
read
API docs:... and:
In other words unless the read method returns -1 there is still more data available to read, but you cannot guarantee that
read
will read exactly the specified number of bytes. The specified number of bytes is the upper bound describing the maximum amount of data it will read.Using
available()
does not guarantee that it counted total available bytes to theend of stream
.Refer to Java
InputStream
'savailable()
method. It says thatAn example solution for your problem can be as follows:
This works for sure on all sizes of input files.