zoukankan      html  css  js  c++  java
  • 00097_序列化流与反序列化流

    1、概述

      (1)用于从流中读取对象的操作流 ObjectInputStream称为 反序列化流;

      (2)用于向流中写入对象的操作流 ObjectOutputStream   称为 序列化流。

      特点:用于操作对象。可以将对象写入到文件中,也可以从文件中读取对象。

    2、对象序列化流ObjectOutputStream

      (1)ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储;

      (2)只能将支持 java.io.Serializable 接口的对象写入流中。

      Person类

     1 import java.io.Serializable;
     2 
     3 public class Person implements Serializable {
     4     private String name;
     5     private int age;
     6 
     7     public Person() {
     8         super();
     9     }
    10 
    11     public Person(String name, int age) {
    12         super();
    13         this.name = name;
    14         this.age = age;
    15     }
    16 
    17     public String getName() {
    18         return name;
    19     }
    20 
    21     public void setName(String name) {
    22         this.name = name;
    23     }
    24 
    25     public int getAge() {
    26         return age;
    27     }
    28 
    29     public void setAge(int age) {
    30         this.age = age;
    31     }
    32 
    33     @Override
    34     public String toString() {
    35         return "Person [name=" + name + ", age=" + age + "]";
    36     }
    37 }

      测试类

     1 import java.io.FileOutputStream;
     2 import java.io.IOException;
     3 import java.io.ObjectOutputStream;
     4 
     5 public class ObjectStreamDemo {
     6     public static void main(String[] args) throws IOException,
     7             ClassNotFoundException {
     8         /*
     9          * 将一个对象存储到持久化(硬盘)的设备上。
    10          */
    11         writeObj();// 对象的序列化。
    12     }
    13 
    14     public static void writeObj() throws IOException {
    15         // 1,明确存储对象的文件。
    16         FileOutputStream fos = new FileOutputStream("D:\Java\obj.object");
    17         // 2,给操作文件对象加入写入对象功能。
    18         ObjectOutputStream oos = new ObjectOutputStream(fos);
    19         // 3,调用了写入对象的方法。
    20         oos.writeObject(new Person("王五", 20));
    21         // 关闭资源。
    22         oos.close();
    23     }
    24 }

      在反序列化程序中运行后能够正常输出Person的相关信息,但是在目录下的文件“obj.object”用文本编辑器打开之后却是乱码的。这是为什么呢?

      因为序列化和反序列化都是基于二进制流的,其实就是将person的相关信息转化为二进制存储在了obj.object这个文件中,那么用文本编辑器打开查看的话当然是会出现乱码的。只有通过反序列化才能将存储的二进制读取出来,然后正常显示在控制台上。

    3、对象反序列化流ObjectInputStream

       ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。支持 java.io.Serializable接口的对象才能从流读取。

     1 import java.io.FileInputStream;
     2 import java.io.IOException;
     3 import java.io.ObjectInputStream;
     4 
     5 public class ObjectStreamDemo2 {
     6     public static void main(String[] args) throws IOException,
     7             ClassNotFoundException {
     8         readObj();// 对象的反序列化。
     9     }
    10 
    11     public static void readObj() throws IOException, ClassNotFoundException {
    12 
    13         // 1,定义流对象关联存储了对象文件。
    14         FileInputStream fis = new FileInputStream("D:\Java\obj.object");
    15 
    16         // 2,建立用于读取对象的功能对象。
    17         ObjectInputStream ois = new ObjectInputStream(fis);
    18 
    19         Person obj = (Person) ois.readObject();
    20 
    21         System.out.println(obj.toString());
    22 
    23     }
    24 }

    4、序列化接口

      (1)当一个对象要能被序列化,这个对象所属的类必须实现Serializable接口。否则会发生异常NotSerializableException异常;

      (2)同时当反序列化对象时,如果对象所属的class文件在序列化之后进行的修改,那么进行反序列化也会发生异常InvalidClassException;

      (3)发生这个异常的原因如下:

      该类的序列版本号与从流中读取的类描述符的版本号不匹配;

      该类包含未知数据类型;

      该类没有可访问的无参数构造方法;

      (4)Serializable标记接口。该接口给需要序列化的类,提供了一个序列版本号。serialVersionUID. 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。
      (5)代码修改如下,修改后再次写入对象,读取对象测试

     1 import java.io.Serializable;
     2 
     3 public class Person implements Serializable {
     4     // 给类显示声明一个序列版本号。
     5     private static final long serialVersionUID = 1L;
     6     private String name;
     7     private int age;
     8 
     9     public Person() {
    10         super();
    11 
    12     }
    13 
    14     public Person(String name, int age) {
    15         super();
    16         this.name = name;
    17         this.age = age;
    18     }
    19 
    20     public String getName() {
    21         return name;
    22     }
    23 
    24     public void setName(String name) {
    25         this.name = name;
    26     }
    27 
    28     public int getAge() {
    29         return age;
    30     }
    31 
    32     public void setAge(int age) {
    33         this.age = age;
    34     }
    35 
    36     @Override
    37     public String toString() {
    38         return "Person [name=" + name + ", age=" + age + "]";
    39     }
    40 }

    5、瞬态关键字transient

      (1)当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient修饰。只要被transient修饰了,序列化时这个属性就不会琲序列化了;

      (2)同时静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。

      (3)代码修改如下,修改后再次写入对象,读取对象测试

     1 import java.io.Serializable;
     2 
     3 public class Person implements Serializable {
     4     /*
     5      * 给类显示声明一个序列版本号。
     6      */
     7     private static final long serialVersionUID = 1L;
     8     private static String name;
     9     private transient/* 瞬态 */int age;
    10 
    11     public Person() {
    12         super();
    13 
    14     }
    15 
    16     public Person(String name, int age) {
    17         super();
    18         this.name = name;
    19         this.age = age;
    20     }
    21 
    22     public String getName() {
    23         return name;
    24     }
    25 
    26     public void setName(String name) {
    27         this.name = name;
    28     }
    29 
    30     public int getAge() {
    31         return age;
    32     }
    33 
    34     public void setAge(int age) {
    35         this.age = age;
    36     }
    37 
    38     @Override
    39     public String toString() {
    40         return "Person [name=" + name + ", age=" + age + "]";
    41     }
    42 }
  • 相关阅读:
    Quartz使用及注意事项
    .Net下性能调优浅析
    .Net下Redis使用注意事项
    WCF服务开发与调用的完整示例
    超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。
    C# DES
    webService访问加密-Soapheader
    WebMethod 属性
    互联网 免费的WebService接口
    利用XPath解析带有xmlns的XML文件
  • 原文地址:https://www.cnblogs.com/gzdlh/p/8098380.html
Copyright © 2011-2022 走看看