我有一个对象集合:
Map<BufferedImage, Map<ImageTransform, Set<Point>>> map
我想把它们写到一个文件中,然后能够在同一个结构中读回来。
我不能按原样编写集合,因为BufferedImage既没有实现Serializable
(也没有实现Externalizable
)接口。所以我需要使用ImageIO
类中的方法来编写图像。
ImageTransform
是实现Serializable
的自定义对象。因此,我相信我的地图集合的值部分应该是可写的。
以下是我将写入文件的步骤:
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
for (BufferedImage image : map.keySet()) {
ImageIO.write(image, "PNG", out); // write the image to the stream
out.writeObject(map.get(image)); // write the 'value' part of the map
}
以下是我从文件中读取的操作:
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
while(true) {
try {
BufferedImage image = ImageIO.read(in);
Map<ImageTransform, Set<Point>> value =
(Map<ImageTransform, Set<Point>>) in.readObject(); // marker
map.put(image, value);
} catch (IOException ioe) {
break;
}
}
然而,这不起作用。我在标记处得到一个java.io.OptionalDataException
。
java.io.OptionalDataException
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1300)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)
我的问题是,首先,写作概念正确吗?ImageIO#write
适合这种情况吗?还是应该考虑使用/存储BufferedImage#getRgb
int[]
阵列?数组是否更紧凑(如中所示,在文件中占用的空间更少)
其次,我应该如何从文件中读取对象?我如何知道何时达到EOF?为什么以上不起作用?
我希望提供的信息足够了,如果你需要更多的信息,请告诉我。
提前谢谢。
它不能像ObjectOutputStream和ObjectInputStream写入/预期的那样工作,当您无序写入图像时会违反特定的文件格式。要成功使用ObjectStreams,您需要遵守ObjectStreams指定的约定。
要做到这一点,您需要创建一个holding类,并使用该类作为映射的键,而不是BufferedImages。这个持有类应该实现Serializable和三个方法(不在任何实际接口中),它们将类标记为在读写过程中需要特殊处理。方法签名必须与指定的完全一致,否则序列化将不起作用。
有关更多信息,请参阅ObjectOutputStream上的文档。
public class ImageHolder implements Serializable {
BufferedImage image;
public ImageHolder(BufferedImage image) {
this.image = image;
}
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
image = ImageIO.read(stream);
}
private void writeObject(ObjectOutputStream stream)
throws IOException {
ImageIO.write(image, "PNG", stream);
}
private void readObjectNoData() throws ObjectStreamException {
// leave image as null
}
然后串行化应该像outputStream.writeObject(map)
一样简单。尽管您需要检查ImageTransform的实现类是否也可以串行化。
"欺骗"并且只有一个对象要序列化的一种方法是将对象组添加到可扩展的可序列化列表中。然后序列化列表。
BTW-I倾向于在序列化对象上使用XMLEncoder
,因为它们可以在以后的JVM中恢复。对于序列化的对象没有这样的保证。
@Ivan c00kiemon5ter V Kanak:"我正在努力保持文件的大小尽可能小,..
考虑到磁盘空间非常便宜,这通常是浪费精力。
*。。所以我想序列化会更好。*
不要猜测。测量
。。我会尝试使用列表,看看效果如何
酷。请注意,如果使用XMLEncoder
,我建议在大多数情况下压缩它。这将减少XML核心的文件大小。这种情况在存储图像时有所不同。
图像格式通常包含不利于Zip进一步压缩的类型的压缩。这可以通过在Zip中的单独条目中存储压缩的XML和"原始"图像来实现。OTOH我想您会发现,考虑到图像条目的最终文件大小,单独压缩XML所节省的字节数是不值得的。