tagomago
tagomago

Reputation: 85

Reading images from a .cbz archive

I want to read images inside a .CBZ archive and store them inside an ArrayList. I have tried the following solution but it has, at least, 2 problems.

  1. I get an OutOfMemory error after adding 10-15 images to the ArrayList
  2. There must be a better way of getting the images inside the ArrayList instead of writing them on a temp file and reading that again.

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

Upvotes: 1

Views: 267

Answers (2)

Andrew Thompson
Andrew Thompson

Reputation: 168825

Each BufferedImage will typically require significantly more memory than the byte[] from which it is constructed. Cache the byte[] and stamp each one out to an image as needed.

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1500675

The "OutOfMemoryError" may or may not be inherent in the amount of data you're trying to store in memory. You may need to change your maximum heap size. However, you can certainly avoid writing to disk - just write to a ByteArrayOutputStream instead, then you can get at the data as a byte array - potentially creating a ByteArrayInputStream round it if you need to. Do you definitely need to add them in your list as BufferedImage rather than (say) keeping each as a byte[]?

Note that if you're able to use Guava it makes the "extract data from an InputStream" bit very easy:

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

Upvotes: 2

Related Questions