[java IO流]之 序列化流和反序列化流(ObjectOutputStream/ObjectInputStream)

小杆子發表於2021-02-10
序列化流:ObjectOutputStream
反序列化流:ObjectInputStream
概述:

ObjectOutputStream將Java物件的基本資料型別和圖形寫入OutputStream。可以使用ObjectInputStream讀取(重構)物件。透過在流中使用檔案可以實現物件的持久儲存。就是講物件儲存到文字檔案中。

實現序列化:

1.類透過實現 java.io.Serializable介面以啟用其序列化功能。

2.未實現此介面的類將無法使用其任何狀態序列化或反序列化,該介面沒有任何方法,是一個標記介面。

3.未實現序列化丟擲為序列化異常:NotSerializableException。

4.序列化資料後,再次修改類檔案,讀取資料會出現問題,使用transient關鍵字宣告不需要序列化的成員變數。

序列化和反序列化程式碼演示:

輸出結果為:小紅|20

package day0506;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

public class demo13 {

public static void main(String[] args) throws FileNotFoundException, 

 IOException, ClassNotFoundException {

  Write();

  Read();//輸出結果為:小紅|20

  }

  //建立讀的方法(返序列化)

  public  static void Read() throws FileNotFoundException, IOException, ClassNotFoundException {

  ObjectInputStream ois=new  ObjectInputStream(new FileInputStream("oos.txt"));

  Object readObject = ois.readObject();

  if (readObject instanceof Person) {

      Person p=(Person) readObject;

      System.out.println(p.getName()+"|"+p.getAge());

  }

  }

  //建立寫的方法(序列化)

  public  static void Write() throws FileNotFoundException, IOException {

  ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("oos.txt"));

  oos.writeObject(new Person("小紅", 20));

  oos.close();

  }

}

//建立人類

class Person  implements Serializable{

  private String name;

  private  int age;

  public Person(String name, int age) {

  super();

  this.name = name;

  this.age = age;

  }

  public Person() {

  super();

  // TODO Auto-generated constructor stub

  }

  @Override

  public String toString() {

  return "person [name=" + name + ", age=" + age + "]";

  }

  public String getName() {

  return name;

  }

  public void setName(String name) {

  this.name = name;

  }

  public int getAge() {

  return age;

  }

  public void setAge(int age) {

  this.age = age;

  }

}
使用transient關鍵字宣告不需要序列化的成員變數。

輸出結果為:小紅|0

package day0506;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

public class demo13 {

public static void main(String[] args) throws FileNotFoundException, 

 IOException, ClassNotFoundException {

  Write();

  Read();//輸出結果為:小紅|0

  }

  //建立讀的方法(返序列化)

  public  static void Read() throws FileNotFoundException, IOException, ClassNotFoundException {

  ObjectInputStream ois=new  ObjectInputStream(new FileInputStream("oos.txt"));

  Object readObject = ois.readObject();

  if (readObject instanceof Person) {

      Person p=(Person) readObject;

      System.out.println(p.getName()+"|"+p.getAge());

  }

  }

  //建立寫的方法(序列化)

  public  static void Write() throws FileNotFoundException, IOException {

  ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("oos.txt"));

  oos.writeObject(new Person("小紅", 20));

  oos.close();

  }

}

//建立人類

class Person  implements Serializable{

  private String name;

  private transient  int age;//防止成員變數序列化

  public Person(String name, int age) {

  super();

  this.name = name;

  this.age = age;

  }

  public Person() {

  super();

  // TODO Auto-generated constructor stub

  }

  @Override

  public String toString() {

  return "person [name=" + name + ", age=" + age + "]";

  }

  public String getName() {

  return name;

  }

  public void setName(String name) {

  this.name = name;

  }

  public int getAge() {

  return age;

  }

  public void setAge(int age) {

  this.age = age;

  }

}

異常名稱: java.io.InvalidClassException

異常字串:

day0506.Person; local class incompatible:
stream classdesc serialVersionUID = 8127820720723137671,
local class serialVersionUID = -5481014064123845604

類在已經被儲存到本地的文字檔案中,如果修改了類,再次讀取(反序列化)會出現序列化Id不配。

解決辦法:

新增靜態序列號

class Person implements Serializable{

  /**

  * 新增固定的序列號,及時隨便修改,也是讀取之前寫入的類,不會報錯。

  */

  private static final long serialVersionUID = -4883211314949864878L;

  String name;

  private transient  int age;

  public Person(String name, int age) {

  super();

  this.name = name;

  this.age = age;

  }

  public Person() {

  super();

  // TODO Auto-generated constructor stub

  }

  @Override

  public String toString() {

  return "person [name=" + name + ", age=" + age + "]";

  }

  public String getName() {

  return name;

  }

  public void setName(String name) {

  this.name = name;

  }

  public int getAge() {

  return age;

  }

  public void setAge(int age) {

  this.age = age;

  }

}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章