【问题标题】:ObjectInputStream Error [duplicate]ObjectInputStream 错误 [重复]
【发布时间】:2009-06-10 20:08:05
【问题描述】:

我正在使用 ObjectOutputStream 创建一个序列化对象文件。然后我使用 ObjectInputStream 和 readObject() 方法从文件中取回对象。

第一次效果很好。这意味着如果文件不存在并且我打开它然后附加任意数量的对象,我可以打开 ObjectInputStream 对象并访问所有对象。

但是,如果我随后打开同一个文件(使用 append 选项)并添加更多对象,ObjectInputStream 对象会收到 java.io.StreamCorruptedException: "invalid type code: AC" 错误,新对象应该从哪里开始。

还有其他人遇到过这种情况吗?我什至回到了 Deitel 书中的一些基本教科书示例,但仍然遇到同样的错误。

编辑:我发现了这一点 - 一旦序列化流关闭并以附加模式重新打开,您可能无法附加到序列化流的末尾。写入似乎可以工作,但是当您稍后再读取该文件时,您将收到 java.io.StreamCorruptedException。在“http://mindprod.com/jgloss/gotchas.html#SERIALIZATION

【问题讨论】:

    标签: java objectoutputstream objectinputstream


    【解决方案1】:

    每个对象都作为对象流的一部分进行序列化,而不是作为个体。像大多数文件格式(但不是 ZIP!)一样,“对象流序列化协议”有一个标题。这是每个新的ObjectInputStream 只希望在文件开头找到的内容。把它放在流的中间是行不通的。流也有反向引用,所以没有对象被写出两次(除非另有说明)。

    所以你需要创建一个新的ObjectInputStream 来匹配每个ObjectOutputStream。有一些内部缓冲,如果这会导致问题,您需要在让Object(In|Out)putStream 处理之前对流进行切片。

    【讨论】:

    • 这里的输出和输入流之间没有直接的关联。它们甚至可能不会在同一天或同一工作站上运行。将信息保存到文件中,稍后另一个进程必须打开和读取。
    【解决方案2】:

    ObjectStream 包含页眉和页脚。它还包含有状态信息,即它写入的内容是基于它已经写入的对象。

    因此,您不能只附加到现有的 ObjectStream。你可以做的是每次重写文件并添加对象,或者用你自己的协议包装流,这样你就可以正确地写入/读取多个流。

    当您使用相同的代码库(尤其是读取/写入的类)读取/写入数据时,ObjectStream 的效果最佳。ObjectStream 并非旨在跨代码版本或在不同应用程序之间移植。

    【讨论】:

    • 我们何时使用了哪个流??请回复
    • @AnshulParashar ObjectOutputStream 和 ObjectInputStream。
    【解决方案3】:

    如果流的生产者和消费者是独立的,那么您每次只覆盖输出文件并添加时间戳文件以便消费者知道其重新加载的时间是有意义的。

    例如,

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多