2012-03-10 3 views
1

Я хочу читать изображения в архиве .CBZ и хранить их внутри ArrayList. Я попробовал следующее решение, но у него есть, по крайней мере, 2 проблемы.Чтение изображений из архива .cbz

  1. я получаю OutOfMemory ошибки после добавления 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? –

+0

Знание разрешения (ширина * высота, возможно, * colordepth) этих изображений также поможет оценить использование памяти. –

ответ

1

«OutOfMemoryError» может или не могут быть присущи количества данных, которые вы пытаетесь сохранить в памяти. Вам может потребоваться изменить максимальный размер кучи. Однако вы можете избежать записи на диск - просто напишите на ByteArrayOutputStream вместо этого, тогда вы можете получить данные в виде байтового массива - потенциально создавая ByteArrayInputStream вокруг него, если вам нужно. Вам определенно нужно добавить их в свой список как BufferedImage, а не (скажем) сохранить их как byte[]?

Обратите внимание, что если вы можете использовать Guava это делает «извлекать данные из InputStream» бит очень легко:

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

Мне кажется странным, что я запускаю OOM, так как эта процедура - это все, что делает мой код до сих пор. Спасибо за подсказку ByteArrayOutputStream. Каковы были бы преимущества хранения их в виде байтов? – tagomago

+0

@AlfioCastorina: Представьте себе, что это некоторые изображения с высоким уровнем сжатия - «BufferedImage» вполне может преобразовать его в представление растрового изображения в памяти для каждого пикселя, которое будет * намного больше, чем данные в файл. –

2

Каждый BufferedImage обычно требует значительно больше памяти, чем byte[] из которого построен. Загрузите byte[] и отметьте каждый из них при необходимости.