繁体   English   中英

向文件写入/读取一系列不同的序列化对象

[英]Write/Read a series of different serialized objects to/from a file

我有一组对象:

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

但是,这不起作用。 我在marker处收到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指定的约定。

为此,您将需要创建一个保持类,并使用该类作为映射的键而不是BufferedImages。 该持有类应实现Serializable和三个方法(不在任何实际接口中),这些方法将Class标记为在读写过程中需要特殊处理。 方法签名必须与指定的完全相同,否则序列化将不起作用。

有关更多信息,请参见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的实现类也是可序列化的。

一种“欺骗”并且只有一个对象要序列化的方法是将对象组添加到可扩展的可序列化列表中。 然后序列化列表。

顺便说一句-我倾向于在序列化的对象上使用XMLEncoder ,因为它们可以在以后的JVM中恢复。 序列化的对象没有这种保证。


@Ivan c00kiemon5ter V卡纳克(V Kanak): “我正在尝试将文件的尺寸保持尽可能小。

鉴于磁盘空间是如此便宜,这通常是浪费的精力。

* ..所以我想序列化对此更好。 *

不要猜。 测量。

..我将尝试使用列表,看看如何进行。 ..

凉。 请注意,如果使用XMLEncoder ,我建议在大多数情况下将其压缩。 这将减少XML碎片的文件大小。 这种情况在存储图像方面有所不同。

图像格式通常包含一种不利于Zip进一步压缩的类型的压缩。 通过将压缩的XML和图像作为“原始”存储在Zip中的单独条目中,可以避免这种情况。 OTOH我认为您会发现仅压缩XML节省的字节数是不值得的-考虑到图像条目的最终文件大小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM