一、读写对象流(学生对象)
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(); } }