Ожидается 0 байтов после writeObject(null), вместо этого я нахожу 5 байтов, что происходит?

Я получаю странные результаты при записи объектов в ByteArrayOutputStream.

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

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

Итак, я пишу ноль в ByteArrayOutputStream, затем, когда я извлекаю байты из этого потока вместо того, чтобы находить 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. Что здесь происходит?


person sonicboom    schedule 23.02.2013    source источник
comment
Почему вы ожидаете нулевые байты? Как поток может передавать значение ссылки на объект «null» без использования каких-либо байтов? Вопрос теряет смысл.   -  person user207421    schedule 24.02.2013


Ответы (2)


Во-первых, вы ничего не пишете, когда пишете null. Вы пишете нулевое значение. Процесс сериализации должен убедиться, что при десериализации вы получите обратно null, поэтому он должен быть каким-то образом представлен. Также могут быть служебные данные в начале, чтобы отметить начало потока.

Когда вы пишете «А», вы не просто ставите букву «А». Вы сериализуете полный объект String. Это должно содержать информацию для десериализатора, чтобы позже восстановить объект String с тем же значением. Итак, есть тип информации и содержание. Само содержимое также будет занимать более одного байта, потому что Java внутренне представляет String как массив char, которые являются 2-байтовыми значениями, а также потому, что длина строки должна быть каким-то образом закодирована (на самом деле я даже удивлен они поместили бы все это всего в 8 байтов).

Изменить: я ознакомился с пояснениями на этой странице. Мы можем использовать это, чтобы понять результаты, которые вы получаете.

В первом примере у вас есть следующие байты:

  • AC ED (это шестнадцатеричный код для -84 -19): STREAM_MAGIC. Магическое значение, указывающее, что это протокол сериализации.
  • 00 05 : ПОТОК_ВЕРСИЯ. Версия 5.
  • 70 (шестнадцатеричный для 112): TC_NULL, представляет нулевое значение.

Во втором примере на самом деле значения, которые вы дали, не соответствуют. Я сам пробовал ваш код, и я получаю это:

  • РЕДАКТОР АС : STREAM_MAGIC
  • 00 05 : ПОТОК_ВЕРСИЯ
  • 74: TC_STRING, представляет новую строку
  • 00 01: длина строки (1)
  • 65: представление UTF8 для «A».

Что касается последнего байта, я, по-видимому, немного ошибся: даже если Java использует внутренне 2-байтовое представление для символа, он кодирует String с помощью UTF8, который использует только один байт для символа «A».

Все специальные значения в формате являются константами в классе ObjectStreamConstants

person Cyrille Ka    schedule 23.02.2013

Null — это такое же значение, как и любое другое. Могут быть случаи, когда это нужно будет написать.

person drone.ah    schedule 23.02.2013