34.5 对象流 读取学生对象、序列化接口、异常处理

 

 一、读写对象流(学生对象)

public class Student implements Serializable {//实现 Serializable接口,生成固定序列号
    private static final long serialVersionUID = -8382241919527639480L;
    String name;
    int age;
//    String gender;

    public Student() {
    }

    public Student(String name,int age) {
        this.name = name;
        this.age = age;
    }



    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
//                ", gender='" + gender + '\'' +
                '}';
    }
}

 

package day33_io_打印流和对象流.ObjectOutputStream_对象流_ObjectInputStream;

import java.io.*;
import java.util.Date;
/*
 * 使用对象输出流和读对象输入流写对象
 * Exception in thread "main" java.io.NotSerializableException: com.itheima_07.Student
 * Serializable:序列化,是一个标识接口,只起标识作用,没有方法
 *                 当一个类的对象需要IO流进行读写的时候,这个类必须实现该接口
 *
 * Exception in thread "main" java.io.EOFException:当输入过程中意外到达文件或流的末尾时,抛出此异常。
 *
 * ClassNotFoundException 要查看的类是否存在(此处指student)
 */
public class O2_ObjectOutput_InputStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        writeMethod();
        readMethod();


    }

    private static void readMethod() throws IOException, ClassNotFoundException {
        //创建输入流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oo.txt"));
        //读取数据
       /*当读取到文章末尾时报错EOFException
        Object obj = ois.readObject();
        System.out.println(obj);

        Object obj1 = ois.readObject();
        System.out.println(obj1);

        Object obj2 = ois.readObject();
        System.out.println(obj2);*/

        try{
            while (true) {
                Object obj = ois.readObject();
                System.out.println(obj);
            }
        }catch (EOFException e) {
            System.out.println("读到末尾了");
        }

        // 释放资源
        ois.close();
    }

    private static void writeMethod() throws IOException {
        //创建输出流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oo.txt"));
        //创建学生对象
        Student s = new Student("zhangsan",18);
        Student s2 = new Student("lisi",20);

        // 写入数据
        oos.writeObject(s);
        oos.writeObject(s2);

        // 释放资源
        oos.close();
    }
}

 

oo.txt

输出

 

 

二、异常处理

上面说到EOFException,因为不知道有几个对象,用try读到末尾时退出

解决方法:使用集合将多个Student对象合到一起,对一个集合进行操作

package day33_io_打印流和对象流.ObjectOutputStream_对象流_ObjectInputStream;

import java.io.*;
import java.util.ArrayList;

/*
 * 解决对象输入流读取对象出现异常的问题
 *      上节说到EOFException,因为不知道有几个对象,用try读到末尾时退出
 *      解决方法:使用集合将多个Student对象合到一起,对一个集合进行操作。
 */
public class O3_解决读取对象时的异常 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //写多个Student对象数据到集合中,由对象流操作集合
        writeArrayMethod();

        //读对象流中的数据,对象流数据转换为集合读取
        readArrayMethod();



    }

    private static void readArrayMethod() throws IOException, ClassNotFoundException {
        //创建对象输入流的对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oo.txt"));
        // 读取对象中数据
        Object obj = ois.readObject();
        //将对象数据转为集合数据读取
        ArrayList<Student> arrli = (ArrayList<Student>)obj;////向下转型,获取具体的子类对象
//        System.out.println(arrli);
        for (Student s : arrli) {
            System.out.println(s);
        }
        // 释放资源
        ois.close();
    }

    private static void writeArrayMethod() throws IOException {
        //创建输出对象流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oo.txt"));

        // 写数据到集合
        ArrayList<Student> arrli = new ArrayList<Student>();
        arrli.add(new Student("zhangsan",28));
        arrli.add(new Student("lisi",30));

        //写数据到对象
        oos.writeObject(arrli);

        // 释放资源
        oos.close();
    }
}

 

 

三、序列号 实现序列化接口出现的黄色警告问题

写出:创建对象输出流对象---创建学生对象---写出学生对象

读入:创建对象输入流对象---读取对象流的对象

问题:在写完成后数据会有一个序列号(不可见),如果这时写入对象(student)发生改变则序列号会发生变化。

   此时读取对象流数据时会报错 InvalidClassException

解决:点击Student类,快捷键alt+enter 选择add ‘serialVersionUID’ 生成一个固定序列号

   好处,这时写完对象数据后即使Student对象发生改变也不会影响读取对象数据

 

实现Serializable接口的类需生成一个序列号

 

package day33_io_打印流和对象流.ObjectOutputStream_对象流_ObjectInputStream;

import java.io.*;

/*
 * 解决对实现序列化接口出现的黄色警告问题
 * Exception in thread "main" java.io.InvalidClassException
 * Exception in thread "main" java.io.InvalidClassException: day33_io_打印流和对象流.ObjectOutputStream_对象流_ObjectInputStream.Student; local class incompatible: stream classdesc serialVersionUID = -4077974485233819946, local class serialVersionUID = -480506088955830645
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)

 * 当 Serialization 运行时检测到某个类具有以下问题之一时,抛出此异常。
        该类的序列版本号与从流中读取的类描述符的版本号不匹配
        该类包含未知数据类型
        该类没有可访问的无参数构造方法

    设置序列号生成快捷方式
    https://blog.csdn.net/Ecloss/article/details/85091023
 *
 * StreamCorruptedException (输入)对象流读取的数据不是(输出)对象流写的数据时报错
 */
public class O4_序列号_序列化接口出现的黄色警告问题 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
//        method();
        method2();
    }

    //读取学生对象
    private static void method2() throws IOException,ClassNotFoundException {
        //创建对象输入流的对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oo.txt"));
        //读取对象
        Object obj = ois.readObject();
        System.out.println(obj);
        //释放资源
        ois.close();
    }

    //写出学生对象
    private static void method() throws IOException{
        //创建对象输出流的对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oo.txt"));
        //创建的学生对象
        Student s = new Student("qian", 28);
        //写出学生对象
        oos.writeObject(s);
        //释放资源
        oos.close();
    }
}

 

posted @ 2019-08-08 11:32  龙桑  阅读(346)  评论(0编辑  收藏  举报