• Java基础知识强化之IO流笔记65:序列化流 和 反序列化流


    1. 什么是 序列化反序列化 ?

        序列化 (Serialization):将对象的状态信息转换为可以存储或传输的形式的过程。比如转化为二进制、xml、json等的过程

    在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。一般的格式是与平台无关的二进制流,可以将这种二进制流持久保存在磁盘上,也可以通过网络将这种二进制流传输到另一个网络结点。

      反序列化(Anti Serialization ):是指把这种二进制流数据还原成对象。也就是将在序列化过程中所生成的二进制串、xml、json等转换成数据结构或者对象的过程

      

       这两个过程结合起来,可以轻松地存储、传输数据。

    2. 序列化流 和 反序列化流:

    序列化流:ObjectOutputStream

    反序列化流:ObjectInputStream

    3. 案例代码演示:

    (1)序列化和反序列化是针对对象进行操作.

    所以我们在使用序列化流(ObjectOutputStream)和 反序列化流(ObjectInputStream)之前,我们先创建一个类:Person,如下:

     1 package cn.itcast_07;
     2 
     3 import java.io.Serializable;
     4 
     5 /*
     6  * NotSerializableException:未序列化异常
     7  * 
     8  * 类通过实现 java.io.Serializable 接口以启用其序列化功能未实现此接口的类将无法使其任何状态序列化或反序列化。
     9  * 该接口居然没有任何方法,类似于这种没有方法的接口被称为标记接口。
    10  * 
    11  *我们修改Person类中的private int age --->  int age,报如下错误: 
    12  *java.io.InvalidClassException: 
    13  * cn.itcast_07.Person; local class incompatible: 
    14  * stream classdesc serialVersionUID = -2071565876962058344, 
    15  * local class serialVersionUID = -8345153069362641443
    16  * 
    17  * 为什么会有问题呢?
    18  *         Person类实现了序列化接口,那么它本身也应该有一个标记值这个标记值表明该Person类实现了序列化接口
    19  *         这个标记值假设是100。
    20  *         开始的时候:(没有问题21  *         Person.class -- id=100
    22  *         write数据: oos.txt -- id=100
    23  *         read数据: oos.txt -- id=100    
    24  * 
    25  *         现在:()
    26  *         Person.class -- id=200(修改Person.java,对应的Person.class文件也就改变了,则会产生新的id27  *         wirte数据:oos.txt -- id=100
    28  *         read数据: oos.txt -- id=100
    29  * 我们在实际开发中,可能还需要使用以前写过的数据,不能重新写入。怎么办呢?
    30  * 回想一下原因是因为它们的id值不匹配。
    31  * 每次修改java文件的内容的时候,class文件的id值都会发生改变。
    32  * 而读取文件的时候,会和class文件中的id值进行匹配。所以,就会出问题。
    33  * 但是呢,如果我有办法,让这个id值在java文件中是一个固定的值,这样,你修改文件的时候,这个id值还会发生改变吗?
    34  * 不会。现在的关键是我如何能够知道这个id值如何表示的呢?
    35  * 不用担心,你不用记住,也没关系,点击鼠标即可。
    36  * 你难道没有看到黄色警告线吗?
    37  * 
    38  * 我们要知道的是:
    39  *         看到类实现了序列化接口的时候,要想解决黄色警告线问题,就可以自动产生一个序列化id值40  *         而且产生这个值以后,我们对类进行任何改动,它读取以前的数据是没有问题的41  * 
    42  * 注意:
    43  *         我一个类中可能有很多的成员变量,有些我不想进行序列化。请问该怎么办呢?
    44  *         使用transient关键字声明不需要序列化的成员变量,使用默认值
    45  */
    46 public class Person implements Serializable {
    47     private static final long serialVersionUID = -2071565876962058344L;
    48 
    49     private String name;
    50 
    51     // private int age;
    52 
    53     private transient int age;
    54 
    55     // int age;
    56 
    57     public Person() {
    58         super();
    59     }
    60 
    61     public Person(String name, int age) {
    62         super();
    63         this.name = name;
    64         this.age = age;
    65     }
    66 
    67     public String getName() {
    68         return name;
    69     }
    70 
    71     public void setName(String name) {
    72         this.name = name;
    73     }
    74 
    75     public int getAge() {
    76         return age;
    77     }
    78 
    79     public void setAge(int age) {
    80         this.age = age;
    81     }
    82 
    83     @Override
    84     public String toString() {
    85         return "Person [name=" + name + ", age=" + age + "]";
    86     }
    87 }

    测试类,如下:

     1 package cn.itcast_07;
     2 
     3 import java.io.FileInputStream;
     4 import java.io.FileOutputStream;
     5 import java.io.IOException;
     6 import java.io.ObjectInputStream;
     7 import java.io.ObjectOutputStream;
     8 
     9 /*
    10  * 序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象 -- 流数据(ObjectOutputStream)
    11  * 反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 -- 对象(ObjectInputStream)
    12  */
    13 public class ObjectStreamDemo {
    14     public static void main(String[] args) throws IOException,
    15             ClassNotFoundException {
    16         // 由于我们要对对象进行序列化,所以我们先自定义一个类Person
    17         // 序列化数据其实就是把对象写到文本文件
    18         // write();
    19 
    20         read();
    21     }
    22 
    23     private static void read() throws IOException, ClassNotFoundException {
    24         // 创建反序列化对象
    25         ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
    26                 "oos.txt"));
    27 
    28         // 还原对象
    29         Object obj = ois.readObject();
    30 
    31         // 释放资源
    32         ois.close();
    33 
    34         // 输出对象
    35         System.out.println(obj);
    36     }
    37 
    38     private static void write() throws IOException {
    39         // 创建序列化流对象
    40         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
    41                 "oos.txt"));
    42 
    43         // 创建对象
    44         Person p = new Person("林青霞", 27);
    45 
    46         // public final void writeObject(Object obj)
    47         oos.writeObject(p);
    48 
    49         // 释放资源
    50         oos.close();
    51     }
    52 }
  • 相关阅读:
    Golang Struct 声明和使用
    docker 中ulimit设置理解
    微服务架构引入的问题及解决方案
    Jenkins 集成Sonar代码质量扫描
    Jenkins和gitlab集成自动构建
    初识微服务架构
    jenkins 集成钉钉机器人通知
    Go 新起点
    shell中的(),{}几种语法用法
    二进制日志配置和运维管理
  • 原文地址:https://www.cnblogs.com/hebao0514/p/4876704.html
Copyright © 2020-2023  润新知