Reputation: 147
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
Upvotes: 5
Views: 3601
Reputation: 111279
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
Upvotes: 0
Reputation: 86409
The ObjectOutputStream writes a header at the beginning.
You can eliminate this header by subclassing ObjectOutputStream and implementing writeStreamHeader().
Upvotes: 2
Reputation: 18320
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.
Upvotes: 3
Reputation: 66263
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.
Upvotes: 0