Reputation: 133
I'm writing a Java applet that need to read some XML and image files inside a ZIP file. The Zip file will be download through HTTP and the applet is unsigned, so I need to use java.util.zip.ZipInputStream
to manipulated the data. There's a problem when I'm trying to read a PNG file inside the Zip file.
The steps I handle the Zip file:
Download the Zip through Http
URL resourceURL = new URL(source);
HttpURLConnection httpConnection= (HttpURLConnection) resourceURL.openConnection();
httpConnection.connect();
InputStream resourceFileIn = httpConnection.getInputStream();
Use ZipInputStream to hold the data downloaded
ZipInputStream resourceZipIn = new ZipInputStream(resourceFileIn);
Iterate through every ZipEntry and extract the corresponding byte array
ArrayList<ExtractedEntry> extractedList = new ArrayList<ExtractedEntry>();
ZipEntry currentEntry;
while ((currentEntry = resourceZipIn.getNextEntry()) != null) {
byte[] byteHolder = new byte[(int) currentEntry.getSize()];
resourceZipIn.read(byteHolder, 0, byteHolder.length);
extractedList.add(new ExtractedEntry(currentEntry.getName(), byteHolder));
}
remarks: every ZipEntry extracted is hold by the following class
public class ExtractedEntry {
private String name;
private byte[] byteArray;
public ExtractedEntry(String name, byte[] byteArray) {
super();
this.name = name;
this.byteArray = byteArray;
}
public String getName() {
return name;
}
public byte[] getByteArray() {
return byteArray;
}
}
Find the file I want to read from in the extracted list
ExtractedEntry bgEntry = null;
for (int j = 0; j < extractedList.size() && bgEntry == null; j++) {
if (extractedList.get(j).getName().equals("background.png")) {
bgEntry = extractedList.get(j);
}
}
Perform specific action according to need
InputStream mapBgIn = new ByteArrayInputStream(bgEntry.getByteArray());
BufferedImage bgEntry = ImageIO.read(bgIn);
I list out only the action of reading the PNG file as that is where I encounter the problem. When I try to read the image in the way mentioned above, I always receive the following error at the last line of step 5.
javax.imageio.IIOException: Error reading PNG image data at com.sun.imageio.plugins.png.PNGImageReader.readImage(Unknown Source)
at com.sun.imageio.plugins.png.PNGImageReader.read(Unknown Source)
at javax.imageio.ImageIO.read(Unknown Source)
at javax.imageio.ImageIO.read(Unknown Source)
at com.quadd.soft.game.wtd.lib.resource.ResourceManager.loadHttpZipRes(ResourceManager.java:685)
Caused by: javax.imageio.IIOException: Unknown row filter type (= 7)!
at com.sun.imageio.plugins.png.PNGImageReader.decodePass(Unknown Source)
at com.sun.imageio.plugins.png.PNGImageReader.decodeImage(Unknown Source)
... 29 more
However, if I read the image in the following way starting from step 3, there's no problem.
ZipInputStream resourceZipIn = new ZipInputStream(resourceFileIn);
ZipEntry testEntry;
while ((testEntry = resourceZipIn.getNextEntry()) != null) {
if (testEntry.getName().equals("background.png")) {
BufferedImage bgEntry = ImageIO.read(resourceZipIn);
}
}
Therefore, I guess that there's some problem with my code at extracting the bytes from java.util.zip.ZipInputStream
and put it back for reading the image. But I'm quite new to manipulating stream so I just couldn't figure out what exactly is the problem. I would like to ask if anyone could point out what mistake I've made in the code which cause the error.
Upvotes: 0
Views: 3318
Reputation: 111329
The read
method does not guarantee that it fills the byte array; it reads only a small block and returns the number of bytes that it read. You need a loop, or use a helper class that does fill the array.
For example
DataInputStream in = new DataInputStream(resourceZipIn);
in.readFully(byteHolder);
in.close();
Upvotes: 2