zoukankan      html  css  js  c++  java
  • ObjectOutputStream 追加写入读取错误

    摘自http://blog.csdn.net/mitkey/article/details/50274543

     

    问题描述:

    用类ObjectOutputStream向文件写读对象时,碰到一个问题:新建一个文件,用输出流ObjectOutputStream向文件连续写几个对象,关闭输出流,然 后读取,这些对象都可以读出;这时在向该文件增加对象,新写的对象就读不出了

    问题出现的原因:

    ObjectOutputStream建立后第一次写入一个对象时, 会在对象数据前写入一些标志的数据“AC ED  00 05”(用二进制方式查看打开),应该是流相关的信息。当你关闭 ObjectOutputStream 后再重新打开往文件里面写对象时(append方式),就会再一次把“AC ED 00 05”写入文件,而这些信息并不是你写入对象的数据,所以当你用ObjectInputStream来读取对象时,流会将除第一个“AC ED 00 05”以外的数据当作各个对象的数据,造成无法解析,所以读取时有一个java.io.StreamCorruptedException出现。 这个可以通过编辑Info.dat来验证,只要将“AC ED 00 05”删除(第一个“AC ED 00 05”保留)就可以正常读出后来加入的对象。 给出一个比较笨的解决方法: 在以后要添加新的对象到Info.dat时,将里面原有的对象读出放入ArrayList中,清空文件,再将对象集一次写入。 

    尝试解决办法: 

    那个“AC ED 00 05”是  ObjectOutputStream.writeSystemHeader()写进去的,你可以继承ObjectOutputStream类,覆盖这个方法。 在你自己的writeSystemHeader()里判断是不是第一次写入一个文件,如果是向一个文件大小不为零的文件追加的话,就调用  super.reset(),如果是第一次写这个文件,不是追加,就调用super.writeSystemHeader() 

    自定义类MyObjectOutputStream 

    [java] view plain copy
    1. /** 
    2.  * 此类继承ObjectOutputStream,重写writeStreamHeader()方法,以实现追加写入时去掉头部信息 
    3.  */  
    4. public static class MyObjectOutputStream extends ObjectOutputStream {  
    5.     private static File f;  
    6.   
    7.     // writeStreamHeader()方法是在ObjectOutputStream的构造方法里调用的  
    8.     // 由于覆盖后的writeStreamHeader()方法用到了f。如果直接用此构造方法创建  
    9.     // 一个MyObjectOutputStream对象,那么writeStreamHeader()中的f是空指针  
    10.     // 因为f还没有初始化。所以这里采用单态模式  
    11.     private MyObjectOutputStream(OutputStream out, File f) throws IOException, SecurityException {  
    12.         super(out);  
    13.     }  
    14.   
    15.     // 返回一个MyObjectOutputStream对象,这里保证了new MyObjectOutputStream(out, f)  
    16.     // 之前f已经指向一个File对象  
    17.     public static MyObjectOutputStream newInstance(File file, OutputStream out) throws IOException {  
    18.         f = file;// 本方法最重要的地方:构建文件对象,两个引用指向同一个文件对象  
    19.         return new MyObjectOutputStream(out, f);  
    20.     }  
    21.   
    22.     @Override  
    23.     protected void writeStreamHeader() throws IOException {  
    24.         // 文件不存在或文件为空,此时是第一次写入文件,所以要把头部信息写入。  
    25.         if (!f.exists() || (f.exists() && f.length() == 0)) {  
    26.             super.writeStreamHeader();  
    27.         } else {  
    28.             // 不需要做任何事情  
    29.         }  
    30.     }  
    31. }  

    测试方法: 

    [java] view plain copy
    1. public static void writeObject() throws Exception {  
    2.     String filename = "test.txt";  
    3.     File f = new File(filename);  
    4.     OutputStream os = new FileOutputStream(f, true);  
    5.     MyObjectOutputStream moos = MyObjectOutputStream.newInstance(f, os);  
    6.     moos.writeObject("abc");  
    7.     moos.writeObject(1);  
    8.     moos.close();  
    9. }  

  • 相关阅读:
    第一次博客作业
    编辑器、编译器、文件、IDE等常见概念辨析
    树、二叉树、查找知识点总结
    二叉排序树
    线性表知识点总结
    c语言文件
    第二次博客作业: 函数+进制转换器v1.0beta
    python作业1
    c语言知识
    第一次博客作业
  • 原文地址:https://www.cnblogs.com/LiuYanYGZ/p/6115835.html
Copyright © 2011-2022 走看看