1

私はオブジェクトのコレクションを持っています:

Map<BufferedImage, Map<ImageTransform, Set<Point>>> map

それらをファイルに書き込んでから、同じ構造体でそれらを読み戻せるようにしたいと考えています。


SerializableBufferedImage は(または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 に達したことをどのように知ることができますか? 上記が機能しないのはなぜですか?

提供された情報で十分であることを願っています。何かについてさらに情報が必要な場合は、お知らせください。
前もって感謝します。

4

2 に答える 2

3

ObjectOutputStream および ObjectInputStream は、画像を順不同で書き込むときに違反する特定のファイル形式を書き込む/期待するため、機能していません。ObjectStreams を正常に使用するには、ObjectStreams によって指定された規約に従う必要があります。

これを行うには、ホールディング クラスを作成し、このクラスを BufferedImages の代わりにマップのキーとして使用する必要があります。この保持クラスは、Serializable と、読み取りおよび書き込み中に特別な処理が必要であることをクラスにマークする 3 つのメソッド (実際のインターフェイスではありません) を実装する必要があります。メソッド シグネチャは、指定されたとおりである必要があります。そうでない場合、シリアル化は機能しません。

詳細については、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 の実装クラスもシリアライズ可能であることを確認する必要があります。

于 2011-06-25T21:17:33.737 に答える
0

「カンニング」してシリアル化するオブジェクトを 1 つだけにする 1 つの方法は、オブジェクトのグループを拡張可能でシリアル化可能なリストに追加することです。次に、リストをシリアル化します。

XMLEncoderところで -後の JVM で復元できるため、シリアル化されたオブジェクトを使用する傾向があります。シリアライズされたオブジェクトにはそのような保証はありません。


@Ivan c00kiemon5ter V Kanak: 「ファイルのサイズをできるだけ小さく保つようにしています..

ディスク容量が非常に安価であることを考えると、これは多くの場合無駄な作業です。

* ..だから、それにはシリアル化の方が良いと思います。*

推測しないでください。測定。

..List を使ってみて、どうなるか見てみます。..

涼しい。を使用する場合はXMLEncoder、ほとんどの場合、圧縮することをお勧めします。これにより、XML の残骸のファイル サイズが縮小されます。この状況は、画像の保存では異なります。

通常、イメージ形式には、Zip によるさらなる圧縮を助長しないタイプの圧縮が組み込まれています。これは、XML を圧縮して保存し、画像を「未加工」として Zip の別のエントリに保存することで回避できます。OTOH 画像エントリの最終的なファイル サイズを考えると、XML だけを圧縮することによって節約されるバイト数は、努力する価値がないことがわかると思います。

于 2011-06-25T19:43:04.770 に答える