1

オブジェクトを ByteArrayOutputStream に書き込んでいるときに、奇妙な結果が得られます。

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(baos);
    os.writeObject(null);

    byte[] objectBytes = baos.toByteArray();
    int objectSize = objectBytes.length;

したがって、ByteArrayOutputStream に null を書き込み、0 バイトを見つける代わりにこのストリームからバイトを取得すると、5 であることがわかります。バイトの値は次のとおりです。

  • [0] => -84
  • [1] => -19
  • [2] => 0
  • [3] => 5
  • [4] => 112

を に変更するos.writeObject(null)os.writeObject("A")、8 バイトになり、これらは -

  • [0] => -84
  • [1] => -19
  • [2] => 0
  • [3] => 5
  • [4] => 116
  • [5] => 0
  • [6] => 65
  • [7] => 8

ここで何が起こっているのか、0バイトを書き込むと、バイト配列を取得するときにバイトが見つかると予想されます。そして、さらに 5 バイトが追加されていることがわかります。したがって、「A」と書くと、バイト配列で 6 バイトが返されるはずですが、8 が返されます。ここで何が起こっているのでしょうか。

4

2 に答える 2

12

まず、書くときは何も書いていませんnull。null 値を書き込んでいます。シリアライゼーション プロセスでは、デシリアライズするときに必ずnullバックを取得する必要があるため、なんらかの方法で表現する必要があります。ストリームの開始をマークするために、開始時にオーバーヘッドが発生する場合もあります。

「あ」と書くときも、ただ「あ」の文字を入れているわけではありません。完全な String オブジェクトをシリアル化しています。これには、デシリアライザーが後で同じ値で String オブジェクトを再構築するための情報が含まれている必要があります。したがって、型情報とコンテンツがあります。Java は内部的に String を の配列として表しchar、これは 2 バイトの値であり、文字列の長さを何らかの方法でエンコードする必要があるため (実際には、それらがすべてを 8 バイトに収める)。

編集:このページの説明を確認しました。それを使用して、得られた結果を理解できます。

最初の例では、次のバイトがあります。

  • AC ED (-84 -19 の 16 進数): STREAM_MAGIC。これがシリアル化プロトコルであることを指定するマジック値。
  • 00 05 : ストリーム_バージョン。バージョン5。
  • 70 (112 の場合は 16 進数): TC_NULL、NULL 値を表します。

2番目の例では、実際に指定した値は対応していません。私はあなたのコードを自分で試してみましたが、次のことがわかりました。

  • AC ED : STREAM_MAGIC
  • 00 05 : ストリーム_バージョン
  • 74 : TC_STRING、新しい文字列を表します
  • 00 01: 文字列の長さ (1)
  • 65: "A" の UTF8 表現。

最後のバイトについては、明らかに少し間違っていました。Java が内部的に char に 2 バイト表現を使用している場合でも、文字 "A" に 1 バイトしか使用しない UTF8 で String をエンコードします。

フォーマット内のすべての特別な値は、クラスObjectStreamConstantsの定数です。

于 2013-02-23T20:27:30.150 に答える
2

Nullは他の値と同じです。書く必要がある場合もあります。

于 2013-02-23T20:29:26.237 に答える