Вопрос

I'm getting some strange results when writing objects to a ByteArrayOutputStream.

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

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

So I write a null to a ByteArrayOutputStream, then when I retrieve the bytes from this stream instead of finding 0 bytes, I find there are 5. The values of the bytes are as follows -

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

If I change the os.writeObject(null) to os.writeObject("A") I get 8 bytes and these are -

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

So what's going on here, if I write 0 bytes I expect to find bytes when I retrieve the byte array. And then I see that it adds an extra 5 bytes. So when I write "A" I expect it to return 6 bytes in the byte array but it returns 8. What is going on here?

Это было полезно?

Решение

First, you are not writing nothing when you write null. You are writing a null value. The serialization process must make sure that when you will deserialize, you will get a null back, so it must be represented in some way. There may also be overhead at the beginning to mark the start of the stream.

When you write "A", also, you are not just putting the "A" character. You are serializing a complete String object. This must contains information for the deserializer to rebuild a String object with the same value later. So there is type information, and the content. The content itself will also take more than one byte, because Java represents internally String as an array of char, which are 2-bytes values, and also because the length of the string must be encoded in some way (actually I'm even surprised they'd put all that in just 8 bytes).

Edit: I have taken a look at the explanations on this page. We can use that to understand the results you obtain.

In the first example, you have the following bytes:

  • AC ED (that's the hexadecimalese for -84 -19): STREAM_MAGIC. A magic value who specifies that this is a serialization protocol.
  • 00 05 : STREAM_VERSION. The version 5.
  • 70 (hexadecimal for 112): TC_NULL, represents a null value.

In your second example, actually the values you gave do not correspond. I have tried your code myself and I obtain that:

  • AC ED : STREAM_MAGIC
  • 00 05 : STREAM_VERSION
  • 74 : TC_STRING, represents a new String
  • 00 01: the length of the string (1)
  • 65: the UTF8 representation of "A".

For the last byte, I was apparently a bit wrong: even if Java uses internally a 2-bytes representation for a char, it encodes String with UTF8, which uses only one byte for the character "A".

All the special values in the format are constants in the class ObjectStreamConstants

Другие советы

Null is a value like any other. There could be cases where it would need to be written.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top