我从文件中读取主题对象,主题类有一个临时缓冲图像列表,但使用自定义读/写对象方法,该方法使用 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
我认为这是一个已知问题。
不能保证
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));
使用 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);