2013-09-16 53 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