BufferedImage使用ObjectStream从文件读取为null

时间:2014-04-21 13:24:17

标签: serialization bufferedimage javax.imageio objectinputstream objectoutputstream

描述

我正在从文件中读取主题对象,Theme类有一个暂时的缓冲图像列表,但使用了一个使用ImageIO读写的自定义读/写Object方法。 问题是我在Theme中读取的第一个BufferedImage总是ok(非null)但是其余的都是null,我认为writeObject方法可能有问题,但是什么?

程序进入文件夹并创建一个主题,其中包含位于该文件夹中的图像。图像没有问题,我使用不同的图像进行了检查,结果是一样的。


DataSetup

public class DataSetup {

    public void write() {

        List<Theme> themes = getThemes(new File("data"));

        try {

            FileOutputStream fos = new FileOutputStream("data/campaign.dat");
            ObjectOutputStream oos = new ObjectOutputStream(fos);

            for(Theme theme : themes) {

                oos.writeObject(theme);
            }

            oos.close();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

主题类

package data;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

public class Theme implements Serializable {

    private static final long serialVersionUID = 1L;

    private String name;
    private transient List<BufferedImage> bufferedImages = new ArrayList<BufferedImage();

    public Theme(String name) {

        this.name = name;
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {

        oos.defaultWriteObject();
        oos.writeInt(bufferedImages.size());

        for(BufferedImage bi : bufferedImages) {

                    //Image type is JPG
            ImageIO.write(bi, Data.IMAGE_TYPE, oos);
        }
            oos.close();
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {

        ois.defaultReadObject();
        final int COUNT = ois.readInt();

        bufferedImages = new ArrayList<BufferedImage>(COUNT);

        for(int i = 0; i < COUNT; i++) {

            bufferedImages.add(ImageIO.read(ois));
        }

        System.out.println("Checking for Theme " + getName());
        for(BufferedImage bi : bufferedImages) {

            System.out.println("Image is null = " + (bi==null));
        }
            ois.close();
    }

    public void addBufferedImage(BufferedImage bi) {bufferedImages.add(bi);}
    public BufferedImage getBufferedImage(int index) {return bufferedImages.get(index);}

    public String getName() {return name;}
    public int getSize() {return bufferedImages.size();}
}

输出

Checking for Theme Animal
Image is null = false
Image is null = true
Image is null = true
Image is null = true
Image is null = true
Checking for Theme Clown
Image is null = false
Image is null = true
Image is null = true
Image is null = true
Checking for Theme Mountain
Image is null = false
Image is null = true
Checking for Theme Space
Image is null = false
Image is null = true
Image is null = true

1 个答案:

答案 0 :(得分:1)

我认为这是一个已知问题。

无法保证ImageReader将读取与ImageWriter最初编写的字节数相同的字节数。它将根据需要读取尽可能多的字节以进行有效解码(由于缓冲,这可能比编写的更多,因为流只是继续)。这可能导致流“错误对齐”#34;并且下一次读取将失败。

解决方法是缓冲每次写入,然后在实际图像字节之前写入每个图像的长度(字节计数),或者简单地写入缓冲的字节数组。

回读时,请确保通过读取或跳过必要数量的额外字节来消耗尽可能多的字节数。

要编写,您可以使用类似于以下的代码:

BufferedImage image = null; // your image
ByteArrayOutputStream bufferStream = new ByteArrayOutputStream();
ImageIO.write(image, "JPEG", bufferStream);

byte[] bufferedBytes = bufferStream.toByteArray();

// Write bufferedBytes to ObjectOutputStream as Object, OR write bufferedBytes.length + bufferedBytes as raw bytes

阅读:

byte[] bytes = ...; // from ObjectInputStream
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes));