反序列化过程怎么引发了 java.io.EOFException异常?

本帖最后由 谢冬 于 2013-3-11 04:19 编辑
  1. package com.itheima_01;

  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectInputStream;
  6. import java.io.ObjectOutputStream;

  7. public class ObjectOutputStreamDemo {
  8.         public static void main(String[] args) throws IOException, Exception {
  9.                 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
  10.                 oos.writeObject(new Person("张三", 20, "男"));
  11.                 oos.writeObject(new Person("王二", 20, "男"));
  12.                 oos.writeObject(new Person("李四", 24, "女"));
  13.                 oos.flush();
  14.                 oos.close();
  15.                 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
  16.                 Person p = null;
  17.                 while((p = (Person)ois.readObject()) != null)
  18.                 {
  19.                         System.out.println(p);
  20.                 }
  21.                 ois.close();
  22.         }
  23. }
复制代码
  1. package com.itheima_01;

  2. import java.io.Serializable;

  3. public class Person implements Serializable{
  4.         private static final long serialVersionUID = 613659699548582156L;
  5.         private String name;
  6.         private int age;
  7.         private String sex;
  8.         public Person(String name, int age, String sex) {
  9.                 super();
  10.                 this.name = name;
  11.                 this.age = age;
  12.                 this.sex = sex;
  13.         }
  14.         @Override
  15.         public String toString() {
  16.                 return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
  17.         }
  18. }
复制代码
控制台的提示信息:
Person [name=张三, age=20, sex=男]
Person [name=王二, age=20, sex=男]
Person [name=李四, age=24, sex=女]
Exception in thread "main" java.io.EOFException
        at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2571)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1315)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
        at com.itheima_01.ObjectOutputStreamDemo.main(ObjectOutputStreamDemo.java:22)
查了文档:当输入过程中意外到达文件或流的末尾时,抛出此异常。

怎么就意外到达文件末尾,这程序好像没什么意外?能处理吗?怎么处理?




本帖最后由 冯海霞 于 2013-3-11 15:16 编辑

{:soso_e100:}//嘿,让我来解决你的这个问题吧。

//首先,我们在程序开发中,反序列化时,不是使用你的这种方式,

//你所使用的这种方式是错误的,是没有根据的,因为我们在查阅API中

//ObjectInputStream的readObject使用说明时,API中并没有说:当对象读到末尾时,返回null。

//正规的方式有两个,当对象不多时,一个一个的读,当对象多时,

//我们可以序列化和反序列化一组对象,这样比较方便。一个一个的读,就是序列化了几个,

//反序列化时,控制for循环的条件再读回来几个。而序列化一组对象,是把

//所有要序列化的对象看作是一个对象数组来使用,在反序列化时一起读回来。

//下面是我对你的代码的改进。(使用的是序列和反序列化一组对象的方式!)

//这也是在开发中最常见的一种方式!!


class ObjectOutputStreamDemo {
        public static void main(String[] args) throws IOException, Exception {

                        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
                        //把多个对象,存到对象数组中。
                        Person[] p = {
                                new Person("张三", 20, "男"),
                                new Person("王二", 20, "男"),
                                new Person("李四", 24, "女")
                        };

                        //序列化一组对象。
                        oos.writeObject(p);
                        oos.flush();
                        oos.close();

                        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
                        //反序列化一组对象。
                        p = (Person[])ois.readObject();
                        //循环输出对象数组中的对象。
                        for(int i=0;i                                 System.out.println(p);
                        }
                        ois.close();
        }
}

class Person implements Serializable{
        private static final long serialVersionUID = 613659699548582156L;
        private String name;
        private int age;
        private String sex;
        public Person(String name, int age, String sex) {
                super();
                this.name = name;
                this.age = age;
                this.sex = sex;
        }
        @Override
        public String toString() {
               //这里跟你上边写的toString是一样的,我这里写的代码好像跟什么东西,冲突了,显示一个笑脸!!!!
                return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
        }
}


在你的循环条件里 while((p = (Person)ois.readObject()) != null)   当所有对象都反序列化后    还会再执行一次对象读取操作  而这时  已经到了文件末尾 所以会报流到达文件尾异常  
                while((p = (Person)ois.readObject()) != null)
                {
                        System.out.println(p);
                        i++;
                        if(i==3){
                                System.out.println(ois.read());//如果为-1 表示文件末尾
                        }
                }
你把循环里面的代码改成这样后 将会先打印-1  再报异常  打印-1表示 已经到达文件末尾  而后  你的循环又去读了一次文件 报了异常

这个异常对程序来说没多大影响 你可以利用这个异常来确定 反序列化已经结束   
如果要避免这个异常  其实你可以将需要序列化的对象放到一个arraylist里面  然后序列化一次   反序列化的时候读取一次就行了  这样就不会报异常了



你可能感兴趣的:(Java)