BufferedImage Read from file using ObjectStream is null

问题描述 投票:0回答:2

说明

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

程序遍历文件夹并创建一个主题,其中包含位于该文件夹中的图像。图片没有问题,我用不同的图片检查过,但结果是一样的。


数据设置

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
serialization bufferedimage javax.imageio objectinputstream objectoutputstream
2个回答
1
投票

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

不能保证

ImageReader
将读取与
ImageWriter
最初写入的字节一样多的字节。它将读取有效解码所需的尽可能多的字节(由于缓冲,这可能比作者写的更多,因为流只是继续)。这可能会导致流“未对齐”,并且下一次读取将失败。

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

回读时,通过读取或跳过必要数量的额外字节,确保您消耗的字节数与写入的字节数完全相同。

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

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

0
投票

使用 ObjectInputStream 再次读取对象时抛出 OptionalDataException。

byte[] bytes = (byte[]) ois.readObject(); // from ObjectInputStream
java.io.OptionalDataException
java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1756)
java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:509)
java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:467)

有什么建议吗?

我用你的示例代码来写图像字节。

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

byte[] imageBytes = baos.toByteArray();
oos.writeObject(imageBytes);
© www.soinside.com 2019 - 2024. All rights reserved.