IO-----序列化和反序列化
阿新 • • 發佈:2020-08-21
當我們把一個物件的資訊儲存到我們的硬碟的軟體當中的時候,我們肯定不想讓別人直接就可以開啟檔案看懂我們儲存的
物件的資訊,所以這時候我們就用到了輸入輸出流之中的物件操作流:
- ObjectOutputStream物件輸出流
- ObjectInputStream物件輸入流
顧名思義Object就是代表物件,所以這兩個流主要就是用來操作物件的。
如果我們想讓我們的物件儲存到硬碟中是下面的這種別人看不懂的文字:
我們就需要藉助物件輸出流。
我們藉助一個案例來分析:
案例:
建立一個學生javabean類,屬性有姓名,性別,年齡,分數,並建立一個學生物件,然後把學生物件的資訊儲存到本專案下的test5_1.txt檔案中,然後在我們需要的時候從
test5_1.txt檔案中讀取儲存過得學生物件的資訊。
分析:
- 把學生物件的資訊儲存檔案中的過程是序列化過程
- 把資訊從檔案中讀取出來是反序列化的過程
那麼我們先解決序列化的過程:
首先需要建立一個學生物件(注意這個物件的建立是有貓膩的)
程式碼:
學生類物件:
public class Student implements Serializable {//如果一個類想要被序列化則必須要實現Serializable介面 private static final long serialVersionUID = 1L;//將本類的序列號固定 private String name;private String sex; private int age; private int result; public Student() { } public Student(String name, String sex, int age, int result) { this.name = name; this.sex = sex; this.age = age; this.result = result; } public String getName() {return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getResult() { return result; } public void setResult(int result) { this.result = result; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", sex='" + sex + '\'' + ", age=" + age + ", result=" + result + '}'; }
一個類的物件如果想要被序列化
- 就一定要實現Serializable介面
implements Serializable
如果在序列化和反序列化的過程中javabean類的內容有多修改,反序列化還想要成功
- 就將本類的序列號寫死
private static final long serialVersionUID = 1L;
接下來我們開始用物件輸出流對學生物件進行序列化操作:
程式碼:
public static void main(String[] args) throws IOException { Student stu = new Student("迪麗熱巴", "女", 18, 98); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test5_1.txt"));//建立一個物件輸出流 oos.writeObject(stu);//注意方法是writeObject,顧名思義,直接寫物件 oos.close();//關流 }
執行後將物件序列化檔案中的結果是:
我相信絕大多數人是看不懂的,所以這樣就大大的提高了資訊的安全性
接下來我們再講反序列化:
先看反序列化程式碼:
public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test5_1.txt"));//獲取物件輸入流 Student stu = (Student) ois.readObject();//反序列化並強轉成物件 System.out.println(stu); ois.close(); }
輸出結果:
但是我們如果在反序列化之前對javabean類中資訊進行修改了,還會不會反序列化成功呢?
這就是我上面提到的序列號固定問題:
- 一個物件在被序列化的過程中jvm虛擬機器會根據javabean類的資訊計算出其對應的序列號
- 那麼我們再序列化之後儲存在檔案中的資訊也會被儲存一份序列號
- 當我們在反序列化之前改變javabean類的資訊就會改變javabean的序列號
- 那麼反序列化的時候檔案中資訊中儲存的序列號就和原來對應的javabean類的序列號就不在同
- 所以反序列化就會失敗
- 如果我們讓序列號寫死:private static final long serialVersionUID = 1L;那麼反序列化就不會出現錯誤了。
對於序列號寫死程式碼private static final long serialVersionUID = 1L;我們其實不必死記硬背:這裡告訴大家一個訣竅:
在IDEA中輸入ArrList按住ctrl點選進入ArrList原始碼:
把數字修改一下不超過long的範圍就行了。。。。。。。。