A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 邹学良 中级黑马   /  2013-3-5 10:09  /  2376 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 邹学良 于 2013-3-6 11:18 编辑

通过ObjectOutputStream向一个文件中多次以追加方式写入object,为什么用ObjectInputStream读取这些object时会产生异常?
想不通到底是什么原因
在网上搜了下,也很多这样的问题回答,但说的不是很明白,望大神解惑

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

3 个回复

倒序浏览
我来回答你的问题,我感觉你的这个问题首先你要先对ObjectOutputStream有一个很好的了解,
ObjectInputStream主要的作用是对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。
ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,
或者用于编组和解组远程通信系统中的实参和形参。 ObjectInputStream 确保从流创建的图形中所有对象的类型
与 Java 虚拟机中显示的类相匹配。使用标准机制按需加载类。
默认情况下,对象的反序列化机制会将每个字段的内容恢复为写入时它所具有的值和类型。
反序列化进程将忽略声明为瞬态或静态的字段。对其他对象的引用使得根据需要从流中读取这些对象。
使用引用共享机制能够正确地恢复对象的图形。反序列化时始终分配新对象,这样可以避免现有对象被重写。

我给你举一个例子,例如,要从由 ObjectOutputStream 中的示例写入的流读取,编码如下;
                 FileInputStream fis = new FileInputStream("t.tmp");
        ObjectInputStream ois = new ObjectInputStream(fis);
        int i = ois.readInt();
        String today = (String) ois.readObject();
        Date date = (Date) ois.readObject();
        ois.close();
  

另外,使用缺省的serializetion的实现时,一个ObjectOutputStream的构造和一个ObjectInputStream的构造必须一一对应.
ObjectOutputStream的构造函数会向输出流中写入一个标识头,而ObjectInputStream会首先读入这个标识头.
因此,多次以追加方式向一个文件中写入object时,该文件将会包含多个标识头.所以用ObjectInputStream来deserialize这个
ObjectOutputStream时,将产生StreamCorruptedException.一种解决方法是可以构造一个
ObjectOutputStream的子类,并覆盖writeStreamHeader()方法.被覆盖后的
writeStreamHeader()方法应判断是否为首次向文件中写入object,羰?
则调用
super.writeStreamHeader();
若否,
即以追加方式写入object时,则应调用
ObjectOutputStream.reset()方法.

希望对你有所帮助,不对之处,还望留言!

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 鼓励鼓励

查看全部评分

回复 使用道具 举报
我在网上也看了看,应该是这个意思。
使用缺省的serializetion的实现时,一个ObjectOutputStream的构造和一个ObjectInputStream的构造必须一一对应(如果你多次以追加方式向一个文件 中写入object,而只用一个ObjectOutputStream来读取,显然成了一对多的关系了,违背了一一对应的原则,所以会报异常)ObjectOutputStream的构造函数会向输出流中写入一个标识头,而ObjectInputStream会首先读入这个标识头。因此,多次以追加方式向一个文件 中写入object时,该文件将会包含多个标识头。所以用ObjectInputStream来deserialize这个ObjectOutputStream时,将产 生StreamCorruptedException。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

回复 使用道具 举报
例如,要写入可通过 ObjectInputStream 中的示例读取的对象,请执行以下操作:


        FileOutputStream fos = new FileOutputStream("t.tmp");
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeInt(12345);
        oos.writeObject("Today");
        oos.writeObject(new Date());

        oos.close();

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马