IO文本_物件操作流
本文主要是在使用IO流做圖書館管理系統時通過將圖書、讀者等物件作為類物件,將其所定義的物件的屬性 進行整體存取,本文主要對其中的ObjectInputStream、ObjectOutputStream學習與理解并通過一定的例子進行總結,
文章目錄
- IO文本_物件操作流
- 物件操作流
- 一、ObjectOutputStream 序列化操作與例外解決
- 二、ObjectInputStream 反序列化操作與例外解決
物件操作流
| ObjectInputStream | ObjectOutputStream | |
|---|---|---|
| 概念 | 反序列化流 | 序列化流 |
| 作用 | 將之前使用 ObjectOutputStream 序列化的原始資料恢復為物件,以流的方式讀取物件, | 把物件轉成位元組資料的輸出到檔案中保存,物件的輸出程序稱為序列化,可實作物件的持久存盤, |
一、ObjectOutputStream 序列化操作與例外解決
一個物件要想序列化,必須滿足兩個條件
① 該類必須實作 java.io.Serializable 介面,
( Serializable 是一個標記介面,不實作此介面的類將不會使任何狀態序列化或反序列化,會拋出 NotSerializableException 的例外,)
import java.io.Serializable;
public static class Reader implements Serializable {
public String name = null;
public int age = 0;
}
如上,上述的靜態類沒有實作任何方法,可看出來它是一個標記介面,
② 該類的所有屬性必須是可序列化的,
(如果有一個屬性不需要可序列化的,則該屬性必須注明是瞬態的,使用transient 關鍵字修飾,)
【注】物件序列化本身就是一個主題,Java IO系列教程主要關注流、reader和writer,目前在網上已經有很多文章探討了物件序列化,鏈接如下:http://java.sun.com/developer/technicalArticles/Programming/serialization/
-----------------舉個栗子
/*自定義的物件輸出流
**/
public class MyObjectOutputStream extends ObjectOutputStream {
/**
* 重寫writeStreamHeader()方法
*/
public MyObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
public void writeStreamHeader() throws IOException {
return;
}
//序列化寫入
public static <T> void setFileObject(File file, T p) throws Exception {
FileOutputStream fos = new FileOutputStream(file, true);//可追加寫入
ObjectOutputStream oos = new ObjectOutputStream(fos);//創建物件操作流
oos.writeObject(p);//寫入
oos.close();//關閉流
}
}
二、ObjectInputStream 反序列化操作與例外解決
【例外1拋出】對于JVM可以反序列化物件,它必須是能夠找到class檔案的類,如果找不到該類的class檔案,則拋出一個ClassNotFoundException 例外,
【例外2拋出】當JVM反序列化物件時,能找到class檔案,但是class檔案在序列化物件之后發生了修改,那么反序列化操作也會失敗,拋出一個 InvalidClassException 例外,
原因如下:
① 該類的序列版本號與從流中讀取的類描述符的版本號不匹配
② 該類包含未知資料型別
③ 該類沒有可訪問的無引數構造方法
【注】除了實作Serializable介面外,用于序列化的類還應包含:
private static final long serialVersionUID=1200L;//值可自定
serialVersionUID的Java的物件序列化API使用該變數來確定反序列化的物件是否已使用相同版本的類進行序列化(寫入),因為它現在正嘗試對其進行反序列化,
想象一個Reader物件被序列化到磁盤上,然后對Reader集合進行更改,
之后,嘗試反序列化存盤的Reader物件,
現在,序列化的Reader物件可能與Reader該類的新版本不對應,
為了檢測此類問題,實作的類Serializable應包含一個serialVersionUID欄位,
如果對類進行了大的更改,則還應該更改其serialVersionUID的值,
解決方法:
① 修改本地的serialVersionUID為流中的serialVersionUID,
② 在當初實作Serializable介面時,就固定一個serialVersionUID,這樣每次編譯就不會自動生成一個新的serialVersionUID,
(白話說:只要有類implements Serializable,最好設定一個獨特的 serialVersionUID )
//反序列化讀出
public static <T> List<T> getFileObject(File file) throws Exception {
List<T> list = new ArrayList<T>();
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = null;
// 判斷是否存在
if (file.exists()) {
while (fis.available() > 0) {
// 每次都new一個新的ObjectInputStream:
ois = new ObjectInputStream(fis);//解決StreamCorruptedException例外
T p = (T) ois.readObject();
list.add(p);
}
ois.close();
return list;
} else {
System.out.println("不存在任何資訊吖~");
return list;
}
}
【注】java.io.StreamCorruptedException: invalid type code: AC 問題解決
1、運用集合:
在第一次序列化物件之前,把要序列化的物件添加到集合中,把這個集合序列化到檔案中,然后每次序列化之前,除了把準備序列化的物件添加到集合中,再把已經序列化的集合反序列化回來添加到集合中,然后再把集合序列化到檔案中,
2、重寫ObjectOutputSream的writeStreamHeader()方法:
判斷是不是第一次寫入,若是則寫入頭部,若不是則不寫入頭部,
3:不重寫ObjectOutputSream的writeStreamHeader()方法,
在反序列化的while回圈中,每次都創建一個新的ObjectInputStream用來讀取header,(本文即采取此措施)
上述栗子中方法的應用:
// 增加讀者基本資訊
public void insertReaderInfo() throws Exception {
System.out.println("#####讀者相關資訊,讀者編號,姓名,出生日期,性別,聯系電話,專業,讀者型別(1、一類 2、二類 3、三類),");
Reader rm = scannerReaderInfo(); //鍵盤輸入要插入的資料的方法,回傳值是Reader物件,
MyObjectOutputStream.setReader(readerfile, rm); //寫入資料到檔案
}
// 查詢讀者資訊
public void selectReaderInfo() throws Exception {
readerfile = new File("src\\dell\\librarymanagementsystem\\data\\readerInfo.txt");
readerslist = MyObjectOutputStream.getReader(readerfile);
// 查詢所有用戶
System.out.println("^_^所有讀者用戶的資訊為:");
for (Reader readers : readerslist) {//回圈輸出
System.out.println(readers);
}
System.out.println();
}
以上就是今天要講的內容,本文僅僅簡單介紹了使用IO物件操作流時會遇到的問題以及簡單的使用吖,歡迎交流~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/278186.html
標籤:python
上一篇:天秀!花費 200W 設計的新版 “小米”圖示,看看用Python怎么繪制?
下一篇:有沒有大佬能救我
