2012-03-10 53 views
1

我想讀取.CBZ存檔內的圖像並將它們存儲在ArrayList中。我嘗試了以下解決方案,但它至少有2個問題。從.cbz存檔讀取圖像

  1. 我加入10-15圖像到ArrayList
  2. 必須有獲取圖像的ArrayList內,而不是一遍上的臨時文件,並閱讀他們寫一個更好的方法後得到一個內存不足錯誤。

public class CBZHandler { 
final int BUFFER = 2048; 
ArrayList<BufferedImage> images = new ArrayList<BufferedImage>(); 

public void extractCBZ(ZipInputStream tis) throws IOException{ 
    ZipEntry entry; 
    BufferedOutputStream dest = null; 
    if(!images.isEmpty()) 
     images.clear(); 
    while((entry = tis.getNextEntry()) != null){ 
     System.out.println("Extracting " + entry.getName()); 
     int count; 
     FileOutputStream fos = new FileOutputStream("temp"); 
     dest = new BufferedOutputStream(fos,BUFFER); 
     byte data[] = new byte[BUFFER]; 
     while ((count = tis.read(data, 0, BUFFER)) != -1) { 
       dest.write(data, 0, count); 
      } 
     dest.flush(); 
     dest.close(); 
     BufferedImage img = ImageIO.read(new FileInputStream("temp")); 
     images.add(img); 
    } 
    tis.close(); 
} 
} 
+1

ImageIO從InputStream中讀取數據。爲什麼不將ZipInputStream('tis')傳遞給'ImageIO.read()'?圖像大小是多少(以字節爲單位),JVM的堆大小是多少? – 2012-03-10 18:38:58

+0

瞭解這些圖像的分辨率(寬*高,可能* colordepth)也有助於估計內存使用量。 – 2012-03-10 18:52:10

回答

1

的「的OutOfMemoryError」 可能或可能不是你想存儲在內存中的數據量所固有的。您可能需要更改最大堆大小。但是,您當然可以避免寫入磁盤 - 只需寫入ByteArrayOutputStream,然後您可以將數據作爲字節數組獲取 - 如果需要,可能會創建一個ByteArrayInputStream。你是否確實需要將它們添加到列表中作爲BufferedImage而不是(比如)將它們保存爲byte[]

請注意,如果你能使用它Guava「從InputStream提取數據」位使得很容易:

byte[] data = ByteStreams.toByteArray(tis); 
+0

我看起來很奇怪,我運行OOM,因爲那個例程是我所有的代碼直到現在。感謝ByteArrayOutputStream提示。將它們作爲字節存儲的優點是什麼? – tagomago 2012-03-10 18:42:09

+0

@AlfioCastorina:想象一下,這些圖像具有很高的壓縮級別 - 'BufferedImage'很可能將它轉換爲每個像素的內存位圖表示,這會比*中的數據大得多*文件。 – 2012-03-10 18:47:58

2

每個BufferedImage通常需要比byte[]從中可以顯著更多的內存建。高速緩存byte[],並根據需要將每一個標記爲圖像。