簡體   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