Question

I am puzzled by the behavior of ObjectOutputStream. It seems like it has an overhead of 9 bytes when writing data. Consider the code below:

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();

The length of the array is always 781, while I would expect it to be (1+96+96)*4 = 772 bytes. I can't seem to find where the 9 bytes go.

Thanks!

--edit: added if(oos!=null) { ... } to prevent NPE

Was it helpful?

Solution

ObjectOutputStream is used to serialize objects. You shouldn't make any assumptions how the data is stored.

If you want to store just the raw data use DataOutputStream instead.

OTHER TIPS

The ObjectOutputStream writes a header at the beginning.

You can eliminate this header by subclassing ObjectOutputStream and implementing writeStreamHeader().

The JavaDoc for ObjectOutputStream tells you:

Primitive data, excluding serializable fields and externalizable data, is written to the ObjectOutputStream in block-data records. A block data record is composed of a header and data. The block data header consists of a marker and the number of bytes to follow the header. Consecutive primitive data writes are merged into one block-data record. The blocking factor used for a block-data record will be 1024 bytes. Each block-data record will be filled up to 1024 bytes, or be written whenever there is a termination of block-data mode. Calls to the ObjectOutputStream methods writeObject, defaultWriteObject and writeFields initially terminate any existing block-data record.

So the blocking stuff might be your missing overhead.

Java's serialization stream begins with a 4-byte header (2-byte "magic number" followed by a 2-byte version). The header is followed by a sequence of block-data and objects entries. There are two kinds of blocks-data entries: "short" and "long." Short blocks have a 2-byte overhead per block and the block can be at most 255 bytes long. Long blocks have a 5-byte overhead but they can be up to 4 GB in length. How long the "long" block can be in practice depends on the size of ObjectOutputStream's internal buffers.

In this case you only have one long data-block entry, so the overhead you see is 4 bytes from the stream header and 5 from the data block, 9 bytes in total.

You'll find the full documentation here: http://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top