Java之IO序列化流

序列化

概述

  • Java提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息。字节序列化写出到文件之后,相当于文件中持久保存了一个对象的信息。反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。对象的数据、对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象。

ObjectOutputStream类

  • java.io.ObjectOutputStream类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。

  • 构造方法

    • ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream

    • 构造举例,代码如下:

      FileOutputStream fileOut = new FileOutputStream("a.txt");
      ObjectOutputStream out = new ObjectOutputStream(fileOut);
      
  • 序列化操作

    • 一个对象要想序列化,必须满足两个条件:

    • 该类必须实现java.ioSerializable接口,Serializable是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSeriableException。

    • 该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用transient关键字修饰。

    package com.io.objectstream;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectOutputStream;
    
    /*
         java.io.ObjectOutputStream extends OutputStream
         ObjectOutputStream:对象的序列化流
         作用:把对象以流的方式写入到文件中保存
    
         构造方法:
                  ObjectOutputStream(OutputStream out)创建一个写入指定的OutputStream的ObjectOutputStream。
                  参数:
                       OutputStream out :字节输出流。
         特有的成员方法:
                  void writeObject(Object obj)将指定的对象写入  ObjectOutputStream。
    
         使用步骤:
                  1.创建ObjectOutputStream对象,构造方法中传递字节输出流。
                  2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
                  3.释放资源
    
         注意:
               序列化和反序列化的时候,会抛出NotSerializableException没有序列化异常
               类通过实现java.io.Serializable接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
               Serializable接口也叫标记型接口
                     要进行序列化和反序列化的类必须实现Serializable接口,就会给类添加一个标记
                     当我们进行序列化和反序列化的时候,就会检测类上是否有这个标记
                          有:就可以序列化和反序列化
                          没有:就会抛出NotSerializableException异常
     */
    public class ObjectOutputstreamDemo01 {
        public static void main(String[] args) throws IOException {
            //1.创建ObjectOutputStream对象,构造方法中传递字节输出流。
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\abc\\person.txt"));
            //2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
            oos.writeObject(new Person("蛇皮",19));//NotSerializableException
            //3.释放资源
            oos.close();
        }
    
    }
    
    

ObjectInputStream类

  • ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。

  • 构造方法

    • ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream。
  • 反序列化操作1

    • 如果能找到一个对象的class文件,我们可以进行反序列化操作,调用ObjectInputStream读取对象的方法:

      public final Object readObject():读取一个对象。

      package com.io.objectstream;
      
      import java.io.FileInputStream;
      import java.io.IOException;
      import java.io.ObjectInputStream;
      
      /*
          java.io.ObjectInputStream extends InputStream
          ObjectInputStream:对象的反序列化流
          作用:把文件中保存的对象,以流的方式读取出来使用
      
          构造方法:
                   	ObjectInputStream(InputStream in)创建从指定的InputStream读取的ObjectInputStream。
                   	参数:
                   	    InputStream in:字节输入流
          特有的成员方法:
                     Object readObject() 从ObjectInputStream读取对象。
          使用步骤:
                      1.创建ObjectInputStream对象,构造方法中传递字节输入流
                      2.使用ObjectInputStream对象中的方法readObject读取保存对象中的文件
                      3.释放资源
                      4.使用读取处理的对象(打印)
       */
      public class ObjectInputStreamDemo01 {
          public static void main(String[] args) throws IOException, ClassNotFoundException {
              // 1.创建ObjectInputStream对象,构造方法中传递字节输入流
              ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\abc\\person.txt"));
              //2.使用ObjectInputStream对象中的方法readObject读取保存对象中的文件
              Object o = ois.readObject();
              //3.释放资源
              ois.close();
              //4.使用读取处理的对象
              System.out.println(o);
          }
      }
      
      

      对于JVM可以反序列化对象,它必须是能找到class文件的类。如果找不到该类的class文件,则抛出一个ClassNotFoundException异常。

  • 反序列化操作2

    • 另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException异常。发生这个异常的原因如下:

      • 该类的序列化版本号与流中读取的类描述的版本号不匹配
      • 该类包含未知数据类型
      • 该类没有可访问的无参数构造方法
    • Serializable接口给需要序列化的类,提供了一个序列化版本号。serialVersionUID该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

          private static final long serialVersionUID = 1L;
          private String name;
          private int age;
      

练习:序列化集合

  • 将存有多个自定义对象的集合序列化操作,保存到list.txt文件中,反序列化list.txt,并遍历集合,打印对象信息。

  • 代码实现:

    package com.io.objectstream;
    
    import java.io.*;
    import java.util.ArrayList;
    
    /*
         练习:序列化集合
    
         分析:
               1.定义一个存储Person对象的ArrayList集合
               2.往ArrayList集合中存储Person对象
               3.创建一个序列化流ObjectOutputStream对象
               4.使用ObjectOutputStream对象中的方法writeObject,对集合进行序列化
               5.创建一个反序列化ObjectInputStream对象
               6.使用ObjectInputStream对象中的方法readObject读取文件中保存的集合
               7.把Object类型的集合转换为ArrayList类型
               8.遍历ArrayList集合
               9.释放资源
     */
    public class TestDemo01 {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            //1.定义一个存储Person对象的ArrayList集合
            ArrayList<Person> list = new ArrayList<>();
            //2.往ArrayList集合中存储Person对象
            list.add(new Person("唐蛇皮",21));
            list.add(new Person("菜虚困",20));
            list.add(new Person("药羊",22));
            //3.创建一个序列化流ObjectOutputStream对象
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\abc\\list.txt"));
            //4.使用ObjectOutputStream对象中的方法writeObject,对集合进行序列化
            oos.writeObject(list);
            //5.创建一个反序列化ObjectInputStream对象
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\abc\\list.txt"));
            //6.使用ObjectInputStream对象中的方法readObject读取文件中保存的集合
            Object o = ois.readObject();
            //7.把Object类型的集合转换为ArrayList类型
            ArrayList<Person> list2 = (ArrayList<Person>)o;
            //8.遍历ArrayList集合
            for (Person p: list2) {
                System.out.println(p);
            }
            //9.释放资源
            ois.close();
            oos.close();
    
        }
    }
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值