3

私はJavaを初めて使用します。GZIPstreamの使い方を学びたいです。私はすでにこれを試しました:

ArrayList<SubImage>myObject = new ArrayList<SubImage>(); // SubImage is a Serializable class

ObjectOutputStream compressedOutput = new ObjectOutputStream(
   new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(
   new File("....")))));
compressedOutput.writeObject(myObject);

ObjectInputStream compressedInput = new ObjectInputStream(
   new BufferedInputStream(new GZIPInputStream(new FileInputStream(
   new File("....")))));
myObject=(ArrayList<SubImage>)compressedInput.readObject();

myObjectプログラムが例外をスローせずにファイルに書き込んだとき、ただしファイルが行に達したとき

myObject=(ArrayList<SubImage>)compressedInput.readObject();

この例外をスローします:

Exception in thread "main" java.io.EOFException: Unexpected end of ZLIB input stream

どうすればこの問題を解決できますか?

4

1 に答える 1

7

出力ストリームをフラッシュして閉じる必要があります。それ以外の場合、少なくとも、はBufferedOutputStreamすべてをファイルに書き込むわけではありません(パフォーマンスの低下を避けるために、大きなチャックで書き込みます)。

電話すればcompressedOutput.flush()それcompressedOutput.close()で十分です。

単純な文字列オブジェクトを作成して、ファイルが適切に作成されているかどうかを確認してみてください。

どのように?ファイルを作成する場合はxxx.txt.gz、好みのzipアプリでファイルを開き、xxx.txtを確認できます。アプリが文句を言う場合、コンテンツは完全に書かれていません。

コメントに対する拡張された回答:さらに多くのデータを圧縮する

シリアル化の変更

独自のオブジェクトである場合は、SubImageオブジェクトの標準のシリアル化を変更できます。java.io.Serializable javadocをチェックして、その方法を確認してください。それはかなり簡単です。

必要なものだけを書く

シリアル化には、書き込むすべてのインスタンスの直前に「サブイメージです」と書き込む必要があるという欠点があります。何が起こるかを事前に知っていれば、必要ありません。したがって、より手動でシリアル化を試みることができます。

リストを作成するには、オブジェクトを作成する代わりに、リストに準拠する値を直接書き込みます。必要なのはDataOutputStreamだけです(ただし、ObjectOutputStreamはDOSであるため、とにかく使用できます)。

dos.writeInt(yourList.size()); // tell how many items
for (SubImage si: yourList) {
   // write every field, in order (this should be a method called writeSubImage :)
   dos.writeInt(...);
   dos.writeInt(...);
   ...
}

// to read the thing just:
int size = dis.readInt();
for (int i=0; i<size; i++) {
   // read every field, in the same order (this should be a method called readSubImage :)
   dis.readInt(...);
   dis.readInt(...);
   ...
   // create the subimage
   // add it to the list you are recreating
}

この方法はより手動ですが、次の場合:

  1. あなたは何が書かれるのか知っています
  2. 多くのタイプでこの種のシリアル化は必要ありません

それはかなり手頃な価格であり、Serializableの対応物よりも明らかに圧縮されています。

オブジェクトをシリアル化したり、文字列メッセージを作成したりするための代替フレームワークがあることに注意してください(xmlの場合はXStream、バイナリメッセージの場合はGoogle Protocol Buffersなど)。そのフレームワークは、バイナリに直接機能するか、文字列を書き込んでから書き込むことができます。

あなたのアプリがこれについてもっと必要とするか、あるいは単に好奇心が強いなら、多分あなたはそれらを見るべきです。

代替のシリアル化フレームワーク

SOを調べたところ、この問題に対処するいくつかの質問(および回答)が見つかりました。

https://stackoverflow.com/search?q=alternative+serialization+frameworks+java

XStreamは非常に簡単で簡単に使用できることがわかりました。そして、JSONはかなり読みやすく簡潔な形式です(そしてJavascriptと互換性があり、プラスになる可能性があります:)。

私は行くべきです:

Object -> JSON -> OutputStreamWriter(UTF-8) -> GZippedOutputStream -> FileOutputStream
于 2012-08-27T10:53:50.043 に答える