2013-09-16 72 views
0

我正在写一个Java小程序,需要读取ZIP文件中的一些XML和图像文件。 Zip文件将通过HTTP下载并且该小程序是无符号的,所以我需要使用java.util.zip.ZipInputStream来操纵数据。当我试图读取Zip文件中的PNG文件时出现问题。从字节数组读取图片

我处理Zip文件的步骤:

  1. 通过HTTP下载zip

    URL resourceURL = new URL(source); 
    HttpURLConnection httpConnection= (HttpURLConnection) resourceURL.openConnection(); 
    httpConnection.connect(); 
    InputStream resourceFileIn = httpConnection.getInputStream(); 
    
  2. 使用ZipInputStream来保存数据下载

    ZipInputStream resourceZipIn = new ZipInputStream(resourceFileIn); 
    
  3. 迭代通过每一个ZipEntry并提取相应的字节数组

    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)); 
    } 
    

    备注:提取每一个ZipEntry的是下面的类

    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; 
        } 
    } 
    
  4. 保持在提取的列表

    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); 
        } 
    } 
    
  5. 找到我想要读取的文件执行根据具体行动需要

    InputStream mapBgIn = new ByteArrayInputStream(bgEntry.getByteArray()); 
    BufferedImage bgEntry = ImageIO.read(bgIn); 
    

我列出只读取PNG文件作为是我遇到的问题采取行动。当我尝试读取上面提到的方式形象,我一直在步骤的最后一行收到以下错误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 

但是,如果我以下列方式读取图像从开始第3步,没有问题。

ZipInputStream resourceZipIn = new ZipInputStream(resourceFileIn); 
ZipEntry testEntry; 
while ((testEntry = resourceZipIn.getNextEntry()) != null) { 
    if (testEntry.getName().equals("background.png")) { 
     BufferedImage bgEntry = ImageIO.read(resourceZipIn); 
    } 
} 

因此,我想,有一些问题,我在提取java.util.zip.ZipInputStream字节代码,并把它放回去,用于读取图像。但我很操纵流,所以我只是无法弄清楚到底是什么问题。我想问问是否有人可以指出我在代码中犯了什么错误,从而导致错误。

回答

1

read方法不保证它填充字节数组;它只读取一个小块并返回它读取的字节数。你需要一个循环,或者使用一个辅助类来填充数组。

例如

DataInputStream in = new DataInputStream(resourceZipIn); 
in.readFully(byteHolder); 
in.close(); 
+0

非常感谢,这立即解决问题。 我只是有另一个关于'read'方法的问题。 InputStream和所有子类的'read'方法是否共享相同的属性,它们不保证填充字节数组? – Edison

+0

并非所有子类:['ByteArrayInputStream'](http://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayInputStream.html#read%28byte [],%20int,%20int%29 )例如保证它将尽可能多地阅读。其他输入流,如'FileInputStream'或'SocketInputStream',不能在不牺牲效率的情况下做出这样的保证。 – Joni