Накладные расходы в Java ObjectOutputStream?

Я озадачен поведением ObjectOutputStream. Похоже, что при записи данных накладные расходы составляют 9 байтов. Рассмотрим код ниже:

float[] speeds = new float[96];
float[] flows = new float[96];

//.. do some stuff here to fill the arrays with data

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos=null;
try {
    oos = new ObjectOutputStream(baos);
    oos.writeInt(speeds.length);
    for(int i=0;i<speeds.length;i++) {
        oos.writeFloat(speeds[i]);
    }
    for(int i=0;i<flows.length;i++) {
        oos.writeFloat(flows[i]);
    }
    oos.flush();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if(oos!=null) {
            oos.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

byte[] array = baos.toByteArray();

Длина массива всегда равна 781, хотя я ожидаю, что она будет (1+96+96)*4 = 772 байта. Я не могу найти, куда деваются 9 байтов.

Спасибо!

--edit: добавлено if(oos!=null) { ... } для предотвращения NPE

4 ответа

Решение

ObjectOutputStream используется для сериализации объектов. Вы не должны делать никаких предположений о том, как хранятся данные.

Если вы хотите хранить только необработанные данные, используйте вместо этого DataOutputStream.

ObjectOutputStream записывает заголовок в начале.

Вы можете устранить этот заголовок путем создания подкласса ObjectOutputStream и реализации writeStreamHeader().

Поток сериализации Java начинается с 4-байтового заголовка (2-байтовое "магическое число", за которым следует 2-байтовая версия). Заголовок сопровождается последовательностью записей данных блока и объектов. Существует два вида ввода данных блоков: "короткий" и "длинный". Короткие блоки имеют 2-байтовую служебную информацию на блок, а длина блока может составлять не более 255 байтов. Длинные блоки имеют 5-байтовую служебную информацию, но могут иметь длину до 4 ГБ. Как долго "длинный" блок может быть на практике, зависит от размера ObjectOutputStreamВнутренние буферы.

В этом случае у вас есть только одна длинная запись в блоке данных, поэтому накладные расходы, которые вы видите, составляют 4 байта от заголовка потока и 5 байтов от блока данных, всего 9 байтов.

Вы найдете полную документацию здесь: http://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html

JavaDoc для ObjectOutputStream сообщает вам:

Примитивные данные, за исключением сериализуемых полей и экстернализуемых данных, записываются в ObjectOutputStream в записях блочных данных. Блок данных записи состоит из заголовка и данных. Заголовок данных блока состоит из маркера и количества байтов, следующих за заголовком. Последовательные примитивные записи данных объединяются в одну запись блочных данных. Коэффициент блокировки, используемый для записи данных блока, составит 1024 байта. Каждая запись блочных данных будет заполнена до 1024 байтов или будет записана всякий раз, когда происходит завершение режима блочных данных. Вызовы методов ObjectOutputStream writeObject, defaultWriteObject и writeFields первоначально завершают любую существующую запись данных блока.

Так что блокирующими вещами могут быть ваши пропущенные накладные расходы.

Другие вопросы по тегам