java複習第8天---8.6---IO流---序列化流和打印流


目錄




內容

1、序列化流

1.1、序列化概述

  之前我在存儲數據的時候,都是基本數據類型。但是當我們想要存儲對象的時候怎麼辦呢?Java提供了一種對象序列化機制。用一個字節序列表示一個對象,包括對象類信息,成員變量、成員方法信息等,然後寫入磁盤或者其他流中,相當於文件中持久化了一個對象,稱爲對象的序列化。
  反之,該字節序列還可以讀取文件中的對象信息,重構對象,稱之爲對象的反序列化。

  • 圖示1.1-1:在這裏插入圖片描述

1.2、ObjectOutputStream

  java.io.ObjectOutputStream類,把Java對象的原始數據類型持久化到文件中。

  • 構造方法
參數列表 描述
OutputStream out 創建一個寫入指定的OutputStream的ObjectOutputStream
  • 常用方法
修飾符 返回值類型 方法名 參數列表 描述
public void writeObject Object obj 將指定的對象寫入ObjectOutputStream。

1.2.1、序列化操作

  • 滿足的條件:

    1. 該類必須實現java.io.Serializable接口,Serializable接口是序列化標記,不實現此接口的類的任何狀態不會被序列化和反序列化。
    2. 該類是所有屬性必須是可序列化的。如果有一個類型不需要序列化,必須註明是瞬態的,使用transient關鍵字聲明。
  • 使用步驟:

    1. 創建ObjectOutputStream對象
    2. 調用ObjectOutputStream類的writeObject 方法,把對象寫入文件中
    3. 釋放資源
  • 示例1.2.1-1:

      package io.stream.serialize;
    
      import java.io.Serializable;
    
      public class Student implements Serializable{
    
    
      	/**
      	 * 
      	 */
      	private static final long serialVersionUID = 1L;
      	private String name;
      	private int age;
      	private char gender;
      	private int score;
    
      	public Student() {}
    
      	public Student(String name, int age, char gender, int score) {
      		this.name = name;
      		this.age = age;
      		this.gender = gender;
      		this.score = score;
      	}
    
      	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;
      	}
    
      	public char getGender() {
      		return gender;
      	}
    
      	public void setGender(char gender) {
      		this.gender = gender;
      	}
    
      	public int getScore() {
      		return score;
      	}
    
      	public void setScore(int score) {
      		this.score = score;
      	}
    
      	@Override
      	public String toString() {
      		return name + "\t" + age + "\t" + gender + "\t" + score;
      	}
    
    
    
      }
    
    
      package io.stream.serialize;
    
      import java.io.FileNotFoundException;
      import java.io.FileOutputStream;
      import java.io.IOException;
      import java.io.ObjectOutputStream;
    
      public class TestSeriabliable1 {
      	public static void main(String[] args) throws FileNotFoundException, IOException {
      		Student s = new Student("gaogzhen", 32, '男', 8000);
      		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("f:\\test\\b.txt"));
    
      		oos.writeObject(s);
    
      		oos.close();
      	}
      }
      測試結果:b.txt內容
       sr io.stream.serialize.Student        I ageC genderI scoreL namet Ljava/lang/String;xp    u7  @t gaogzhen
      字節碼文件,直接打開,看不懂
    

1.3、ObjectInputStream

&esmp; ObjectInputStream類,把之前ObjectOutputStream類序列化到文件中的對象,反序列化之後,重構爲對象。

  • 構造方法:
參數列表 描述
InputStream in 創建從指定的InputStream讀取的ObjectInputStream。
  • 常用方法
修飾符 返回值類型 方法名 參數列表 描述
public Object readOject 從ObjectInputStream讀取一個對象。
  • 使用步驟:

    1. 創建ObjectOutputStream對象
    2. 調用ObjectOutputStream類的writeObject 方法,把對象寫入文件中
    3. 釋放資源
  • 示例:1.3-1:讀取b.txt序列化的對象並顯示

      package io.stream.serialize;
    
      import java.io.FileInputStream;
      import java.io.FileNotFoundException;
      import java.io.IOException;
      import java.io.ObjectInputStream;
    
      public class TestUnSerialize1 {
      	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
      		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("f:\\test\\b.txt"));
      		Student s = (Student) ois.readObject();
      		ois.close();
      		System.out.println(s);
      	}
      }
      測試結果:
      gaogzhen	32	男	8000
    

1.4、transient關鍵字

  意爲瞬態,被transient修飾的成員變量不能被序列化

  • 示例1.4-1:

      上例中的Student 的age 用transient修飾
      private transient int age;
      
      package io.stream.serialize;
    
      import java.io.FileInputStream;
      import java.io.FileNotFoundException;
      import java.io.FileOutputStream;
      import java.io.IOException;
      import java.io.ObjectInputStream;
      import java.io.ObjectOutputStream;
    
      public class TestTransient1 {
      	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
      		Student s = new Student("gaogzhen", 32, '男', 8000);
      		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("f:\\test\\b.txt"));
    
      		oos.writeObject(s);
    
      		oos.close();
    
      		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("f:\\test\\b.txt"));
      		Student s1 = (Student) ois.readObject();
      		ois.close();
      		System.out.println(s1);
      	}
      }
      測試結果:
      gaogzhen	0	男	8000
    

1.5、InvalidClassException

  當JVM反序列化對象時,能找到class文件,但是class文件的序列化對象之後發生了修改,那麼反序列化操作會失敗,拋出InvalidClassException異常。發生此異常的原因:

  • 該類的序列號於從六種讀取的類描述符的版本號不匹配
  • 該類包含未知的數據類型
  • 該類沒有可訪問的無參構造函數

1.6、serialVersionUID

  serialVersionUID的取值是Java運行時環境根據類的內部細節自動生成的。如果對類的源代碼作了修改,再重新編譯,新生成的類文件的serialVersionUID的取值有可能也會發生變化。
  類的serialVersionUID的默認值完全依賴於Java編譯器的實現,對於同一個類,用不同的Java編譯器編譯,有可能會導致不同的 serialVersionUID,也有可能相同。爲了提高serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,爲它賦予明確的值。

顯式地定義serialVersionUID有兩種用途:
    1、 在某些場合,希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有相同的serialVersionUID;
    2、 在某些場合,不希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有不同的serialVersionUID。

2、打印流

  java.io.PrintStream打印流。PrintStream爲其他輸出流添加了功能,使它們能夠方便的打印各數據值表示形式。

  • 特點

    1. 只負責數據的輸出,不負責數據的讀取
    2. 與其它輸出流不同,PrintStream永遠不會拋出IOException
  • 特有方法

    • void print(任意類型):打印任意類型的數據
    • void println(任意類型):打印任意類型的數據,並且換行
  • 構造方法

參數列表 描述
File file 輸出目的地爲文件
String fileName 輸出目的地文件
OutputStream out 輸出到其他流
  • 繼承自父類的方法
修飾符 返回值類型 方法名 參數列表 描述
public void close 關閉流,釋放資源
public void flush 刷新此輸出流,並強制任何緩衝的字節寫出
public void write byte[] b 將 b.length字節從指定的字節數組寫入此輸出流。
public void write byte[] b, int off, int len 從指定的字節數組寫入 len個字節,從偏移 off開始到此流。
public abstract void write int b 將指定的字節寫入此流。
  • 注意:

    • 如果使用繼承自父類的write方法寫數據,那麼查看數據的時候會查看編碼表
    • 如果使用特有的print或者println方法寫數據,原樣輸出
  • 示例2-1:

      package io.stream.print;
    
      import java.io.PrintStream;
    
      public class TestPrintStream1 {
      	public static void main(String[] args) {
      		PrintStream ps = new PrintStream(System.out);
    
      		ps.write(97);
      		ps.println();
      		ps.println(97);
      	}
      }
      測試結果:
      a
      97
    

後記

本項目爲參考某馬視頻開發,相關視頻及配套資料可自行度娘或者聯繫本人。上面爲自己編寫的開發文檔,持續更新。歡迎交流,本人QQ:806797785

前端項目源代碼地址:https://gitee.com/gaogzhen/vue-leyou
後端JAVA源代碼地址:https://gitee.com/gaogzhen/JAVA
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章