java 如何序列化包含 BufferedImages 的对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15058663/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 18:20:56  来源:igfitidea点击:

How to serialize an object that includes BufferedImages

javaimageserializationdeserializationbufferedimage

提问by scaevity

I'm trying to create a simple image editing program in java. I made an ImageCanvasobject that has all the information about the image that is being edited (some basic properties, list of effects being applied, a list of BufferedImagelayers, etc.) and I wanted a simple way to save it to disk so it could be opened again later.

我正在尝试用 Java 创建一个简单的图像编辑程序。我制作了一个ImageCanvas对象,其中包含正在编辑的图像的所有信息(一些基本属性、应用的效果列表、BufferedImage图层列表等),我想要一种简单的方法将其保存到磁盘,以便它可以后来又开了。

I figured that using Java's defualt Serializableinterface might be exactly what I was looking for and I could just write the entire object to file and read it back into memory again at a later time. However, ImageCanvasincludes an ArrayList<BufferedImage>, and BufferedImage's are not serializable (everything else is).

我认为使用 Java 的默认Serializable接口可能正是我正在寻找的,我可以将整个对象写入文件并在稍后再次将其读回内存。但是,ImageCanvas包括ArrayList<BufferedImage>, 和BufferedImage是不可序列化的(其他都是)。

I know it is possible to override the writeObject()and readObject()methods, but I have never done so and I was wondering if there is any easy way to have Java serialize everything else and have some custom way to read/write the BufferedImage's to disk? Or is there some other way to easily write the entire ImageCanvasobject to disk that I'm overlooking? Eventually I might implement my own custom image file type, but for right now I wanted a quick and easy way to save files temporarily while I am testing (the ImageCanvasclass will change a lot, so I didn't want to have to keep updating my custom file type before I have it finalized).

我知道可以覆盖writeObject()readObject()方法,但我从来没有这样做过,我想知道是否有任何简单的方法可以让 Java 序列化其他所有内容,并有一些自定义的方式来读/写BufferedImage's 到磁盘?或者是否有其他方法可以轻松地将整个ImageCanvas对象写入我忽略的磁盘?最终我可能会实现我自己的自定义图像文件类型,但现在我想要一种快速简便的方法来在我测试时临时保存文件(ImageCanvas类会发生很大变化,所以我不想一直更新我的在我最终确定之前自定义文件类型)。

回答by Sam Barnum

make your ArrayList<BufferedImage>transient, and implement a custom writeObject()method. In this, write the regular data for your ImageCanvas, then manually write out the byte data for the images, using PNG format.

使您的ArrayList<BufferedImage>瞬态,并实现自定义writeObject()方法。在此,为 ImageCanvas 写入常规数据,然后使用 PNG 格式手动写出图像的字节数据。

class ImageCanvas implements Serializable {
    transient List<BufferedImage> images;

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        out.writeInt(images.size()); // how many images are serialized?
        for (BufferedImage eachImage : images) {
            ImageIO.write(eachImage, "png", out); // png is lossless
        }
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        final int imageCount = in.readInt();
        images = new ArrayList<BufferedImage>(imageCount);
        for (int i=0; i<imageCount; i++) {
            images.add(ImageIO.read(in));
        }
    }
}

回答by Darrell Teague

Serialization is pretty straight-forward in that it persists static data. You are otherwise in the right place with read/write object in the Serialization family of methods. Think about what a "BufferedImage" is. It is a buffered streaming implementation. To serialize, the data must be flushed out to a static object like a byte[] array and then THAT object may be serialized/deserialized into/out of a BufferedImage such that the buffered streaming now comes in/out of that byte[] array.

序列化非常简单,因为它保留静态数据。否则,您在序列化方法系列中使用读/写对象是正确的。想想“BufferedImage”是什么。它是一个缓冲流实现。要序列化,必须将数据刷新到像 byte[] 数组这样的静态对象,然后该对象可以序列化/反序列化到 BufferedImage 中/从 BufferedImage 中取出,这样缓冲的流现在就可以进入/退出该 byte[] 数组.