ObjectOutputStream和ObjectInputStream的基本使用詳解
目錄
1、ObjectOutputStream的使用
--1.1、構(gòu)造函數(shù)
--1.2、常用的方法
----1.2.1、將對(duì)象寫(xiě)入到文件中永久存儲(chǔ)
2、ObjectInputStream的使用
--2.1、構(gòu)造函數(shù)
--2.2、常用的方法
----2.2.1、將已經(jīng)序列化的對(duì)象反序列化
3、小結(jié)
在我們講解對(duì)象輸出流和對(duì)象輸入流之前,我們首先要明確兩個(gè)概念:
序列化和反序列化:
將一個(gè)特定的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為一組字節(jié)的過(guò)程稱(chēng)之為序列化
將一組字節(jié)轉(zhuǎn)換為特定的數(shù)據(jù)結(jié)構(gòu)的過(guò)程稱(chēng)之為反序列化
持久化:
- 將數(shù)據(jù)寫(xiě)入硬盤(pán)長(zhǎng)久保存的過(guò)程稱(chēng)之為持久化
1、ObjectOutputStream的使用
ObjectOutputStream是一個(gè)高級(jí)流, 將 Java 對(duì)象的基本數(shù)據(jù)類(lèi)型和圖形寫(xiě)入 OutputStream??梢允褂?ObjectInputStream 讀?。ㄖ貥?gòu))對(duì)象。通過(guò)在流中使用文件可以實(shí)現(xiàn)對(duì)象的持久存儲(chǔ)。如果流是網(wǎng)絡(luò)套接字流,則可以在另一臺(tái)主機(jī)上或另一個(gè)進(jìn)程中重構(gòu)對(duì)象。
注意:只能將支持 java.io.Serializable 接口的對(duì)象寫(xiě)入流中。每個(gè) serializable 對(duì)象的類(lèi)都被編碼,編碼內(nèi)容包括類(lèi)名和類(lèi)簽名、對(duì)象的字段值和數(shù)組值,以及從初始對(duì)象中引用的其他所有對(duì)象的閉包。
1.1、構(gòu)造函數(shù)
//為完全重新實(shí)現(xiàn) ObjectOutputStream 的子類(lèi)提供一種方法,讓它不必分配僅由 ObjectOutputStream 的實(shí)現(xiàn)使用的私有數(shù)據(jù)。
protected ObjectOutputStream();
//創(chuàng)建寫(xiě)入指定 OutputStream 的 ObjectOutputStream。此構(gòu)造方法將序列化流部分寫(xiě)入底層流;調(diào)用者可以通過(guò)立即刷新流,確保在讀取頭部時(shí),用于接收 ObjectInputStreams 構(gòu)造方法不會(huì)阻塞。
public ObjectOutputStream(OutputStream out);
1.2、常用的方法
我們這里重點(diǎn)講述的是將一個(gè)對(duì)象實(shí)例化之后存儲(chǔ)到文件中,其他的write()方法請(qǐng)參看API。
//將指定的對(duì)象寫(xiě)入 ObjectOutputStream。對(duì)象的類(lèi)、類(lèi)的簽名,以及類(lèi)及其所有超類(lèi)型的非瞬態(tài)和非靜態(tài)字段的值都將被寫(xiě)入。
public final void writeObject(Object obj);
1.2.1、將對(duì)象寫(xiě)入到文件中永久存儲(chǔ)
Person類(lèi)
import java.io.Serializable;
import java.util.ArrayList;
//Person類(lèi)實(shí)現(xiàn)了Serializable接口,所以該類(lèi)才能被序列化;反之,如果沒(méi)有實(shí)現(xiàn)該接口的類(lèi)則不能被序列化。
public class Person implements Serializable{
/**
* 序列化的ID,只要加了該版本號(hào),在反序列化的時(shí)候不論你的類(lèi)的屬性是否改變,只要是版本號(hào)不變那么盡經(jīng)可能的兼容新版本。
* 如果版本號(hào)改變了,那么反序列化的過(guò)程中就會(huì)拋出異常。
*/
private static final long serialVersionUID = 6871740251451383067L;
private String name;
private int age;
private char sex;
private ArrayList<String> other;
public Person(){
}
public Person(String name, int age, char sex, ArrayList<String> other) {
super();
this.name = name;
this.age = age;
this.sex = sex;
this.other = other;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age)throws Exception {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public ArrayList<String> getOther() {
return other;
}
public void setOther(ArrayList<String> other) {
this.other = other;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
將Person對(duì)象寫(xiě)入到文件中
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import tools.Person;
/**
* ObjectOutputStream:高級(jí)流,對(duì)象輸出流,只能將支持 java.io.Serializable 接口的對(duì)象寫(xiě)入流中
*
* 將一個(gè)特定的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為一組字節(jié)的過(guò)程稱(chēng)之為序列化
* 將一組字節(jié)轉(zhuǎn)換為特定的數(shù)據(jù)結(jié)構(gòu)的過(guò)程稱(chēng)之為反序列化
* 將數(shù)據(jù)寫(xiě)入硬盤(pán)長(zhǎng)久保存的過(guò)程稱(chēng)之為持久化
*
* @author Administrator
*
*/
public class OOSDemo01 {
public static void main(String[] args){
try {
ArrayList<String> other=new ArrayList<String>();
other.add("清華大學(xué)");
other.add("軟件學(xué)院");
other.add("軟件工程");
Person person=new Person("小明", 22, '男', other);
FileOutputStream fos=new FileOutputStream("OOS.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
//將一個(gè)對(duì)象經(jīng)行序列化時(shí)需要實(shí)現(xiàn)Serializable接口
oos.writeObject(person);
oos.flush();
oos.close();
System.out.println("對(duì)象寫(xiě)入成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、ObjectInputStream的使用
ObjectInputStream也是一個(gè)高級(jí)流,對(duì)以前使用 ObjectOutputStream 寫(xiě)入的基本數(shù)據(jù)和對(duì)象進(jìn)行反序列化。
2.1、構(gòu)造函數(shù)
//為完全重新實(shí)現(xiàn) ObjectInputStream 的子類(lèi)提供一種方式,讓它不必分配僅由 ObjectInputStream 的實(shí)現(xiàn)使用的私有數(shù)據(jù)。
protected ObjectInputStream();
//創(chuàng)建從指定 InputStream 讀取的 ObjectInputStream。從流讀取序列化頭部并予以驗(yàn)證。在對(duì)應(yīng)的 ObjectOutputStream 寫(xiě)入并刷新頭部之前,此構(gòu)造方法將阻塞。
public ObjectInputStream(InputStream in);
2.2、常用的方法
我們這里;里主要講述的是將已經(jīng)序列化之后存儲(chǔ)在文件中的對(duì)象反序列化的過(guò)程,其他的read()方法請(qǐng)參看API。
//從 ObjectInputStream 讀取對(duì)象。對(duì)象的類(lèi)、類(lèi)的簽名和類(lèi)及所有其超類(lèi)型的非瞬態(tài)和非靜態(tài)字段的值都將被讀取。
public final Object readObject();
注意看,以上的方法返回的是一個(gè)Object,所以我們?cè)诜葱蛄谢倪^(guò)程中需要強(qiáng)制轉(zhuǎn)換為我們所需要的類(lèi)型。
2.2.1、將已經(jīng)序列化的對(duì)象反序列化
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import tools.Person;
/**
* ObjectInputStream:高級(jí)流,對(duì)象輸入流
* ObjectInputStream 對(duì)以前使用 ObjectOutputStream 寫(xiě)入的基本數(shù)據(jù)和對(duì)象進(jìn)行反序列化。
* 有支持 java.io.Serializable 或 java.io.Externalizable 接口的對(duì)象才能從流讀取。
* @author Administrator
*
*/
public class OISDemo01 {
public static void main(String[] args){
try {
FileInputStream fis=new FileInputStream("OOS.txt");
ObjectInputStream ois=new ObjectInputStream(fis);
Person person=(Person)ois.readObject();
System.out.println(person.getName());
System.out.println(person.getAge());
System.out.println(person.getSex());
ArrayList<String> other=person.getOther();
for (String string : other) {
System.out.println(string);
}
ois.close();
System.out.println("反序列化成功!");
} catch (Exception e) {
e.printStackTrace();
}
System.exit(0);
}
}
運(yùn)行結(jié)果:3、小結(jié)
ObjectOutputStream 和 ObjectInputStream 分別與 FileOutputStream 和 FileInputStream 一起使用時(shí),可以為應(yīng)用程序提供對(duì)對(duì)象圖形的持久存儲(chǔ)。ObjectOutputStream用于序列化對(duì)象,ObjectInputStream 用于恢復(fù)那些以前序列化的對(duì)象(反序列化)。其他用途包括使用套接字流在主機(jī)之間傳遞對(duì)象,或者用于編組和解組遠(yuǎn)程通信系統(tǒng)中的實(shí)參和形參。