我对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个字节的位置。
谢谢!
- 编辑:添加if(oos!= null){...}以防止NPE
答案 0 :(得分:3)
ObjectOutputStream用于序列化对象。您不应该假设数据是如何存储的。
如果您只想存储原始数据,请使用DataOutputStream。
答案 1 :(得分:1)
ObjectOutputStream在开头写入标题。
您可以通过继承ObjectOutputStream并实现writeStreamHeader()来消除此标头。
答案 2 :(得分:0)
ObjectDutputStream的JavaDoc告诉您:
原始数据(不包括可序列化字段和可外部化数据)将写入块数据记录中的ObjectOutputStream。块数据记录由标题和数据组成。块数据头由标记和标头后面的字节数组成。连续的原始数据写入被合并到一个块数据记录中。用于块数据记录的阻塞因子将是1024字节。每个块数据记录将填充最多1024个字节,或者在块数据模式终止时写入。调用ObjectOutputStream方法writeObject,defaultWriteObject和writeFields最初会终止任何现有的块数据记录。
所以阻塞的东西可能是你失去的开销。
答案 3 :(得分:0)
Java的序列化流以4字节标头开头(2字节“幻数”后跟2字节版本)。标题之后是一系列块数据和对象条目。块数据条目有两种:“短”和“长”。短块每个块的开销为2字节,块最多可以为255个字节。长块具有5字节的开销,但它们的长度最多可达4 GB。 “长”块在实践中可以使用多长时间取决于ObjectOutputStream
内部缓冲区的大小。
在这种情况下,您只有一个长数据块条目,因此您看到的开销是来自流标头的4个字节和来自数据块的5个字节,总共9个字节。
您可以在此处找到完整的文档:http://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html