我正在使用ObjectOutputStream来创建序列化对象的文件。然后我使用ObjectInputStream来使用readObject()方法将对象从文件中取出。
第一次效果很好。这意味着如果文件不存在而我打开它然后附加任意数量的对象,我可以打开ObjectInputStream对象并访问所有对象。
但是,如果我随后打开相同的文件(使用append选项)并添加更多对象,则ObjectInputStream对象将获取java.io.StreamCorruptedException:“无效的类型代码:AC”错误,其中新对象应该开始。< / p>
有没有其他人遇到这个?我甚至回到Deitel书中的一些基本教科书例子,但仍然得到同样的错误。
编辑:我发现了这一点 - 一旦关闭并在追加模式下重新打开,您可能无法附加到序列化流的末尾。写入似乎有效,但是当您稍后再读取该文件时,您将获得java.io.StreamCorruptedException。在“http://mindprod.com/jgloss/gotchas.html#SERIALIZATION”
答案 0 :(得分:4)
每个物体都被作为物体流的一部分而被作为个体的一部分而被作为一个物体被固定化。与大多数文件格式(但不是ZIP!)一样,“对象流序列化协议”具有标题。这是每个新ObjectInputStream
期望仅在文件开头找到的内容。将它放在流中间不会工作。此流也有反向引用,因此没有对象被写出两次(除非另有说明)。
因此,您需要创建一个新的ObjectInputStream
来匹配每个ObjectOutputStream
。存在一些内部缓冲,如果这会导致问题,则需要在将流Object(In|Out)putStream
放在其上之前对流进行切片。
答案 1 :(得分:1)
如果流的生产者和消费者是独立的,那么每次只覆盖输出文件并添加时间戳文件以便消费者知道重新加载的时间是有意义的。
例如,
SomeObject[] obj = new SomeObject[numObjects];
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file");
out.writeObject(obj);
out.close();
long ts = System.currentTimeMillis();
ObjectOutputStream tout =
new ObjectOutputStream(new FileOutputStream("timestamp.obj");
tout.writeObject(new Long(ts));
然后,消费者可以每隔几分钟轮询一次timestamp.obj文件,如果已经更改,则从流中重新打开SomeObject[]
。
ObjectInputStream in =
new ObjectInputStream(new FileInputStream("timestamp.obj"));
Long ts = (Long)in.readObject();
if (ts > prevts) {
ObjectInputStream in2 = new ObjectInputStream(new FileInputStream("file"));
SomeObject[] obj = (SomeObject[])in.readObject();
prevts = ts;
}
答案 2 :(得分:1)
ObjectStream包含页眉和页脚。它还包含有状态信息,即它所写的内容基于它已经写入的对象。
因此,您不能只追加到现有的ObjectStream。你可以做的是每次重写文件并添加对象,或者使用你自己的协议包装流,这样你就可以正确地写/读多个流。
当您使用相同的代码库读取/写入数据时,ObjectStream的效果最佳(特别是对于读取/写入的类)ObjectStream不能在代码版本之间或不同应用程序之间移植。