ObjectOutputStream和ObjectInputStream的基本使用詳解
目錄
1、ObjectOutputStream的使用
--1.1、構(gòu)造函數(shù)
--1.2、常用的方法
----1.2.1、將對象寫入到文件中永久存儲
2、ObjectInputStream的使用
--2.1、構(gòu)造函數(shù)
--2.2、常用的方法
----2.2.1、將已經(jīng)序列化的對象反序列化
3、小結(jié)
在我們講解對象輸出流和對象輸入流之前,我們首先要明確兩個概念:
序列化和反序列化:
將一個特定的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為一組字節(jié)的過程稱之為序列化
將一組字節(jié)轉(zhuǎn)換為特定的數(shù)據(jù)結(jié)構(gòu)的過程稱之為反序列化
持久化:
- 將數(shù)據(jù)寫入硬盤長久保存的過程稱之為持久化
1、ObjectOutputStream的使用
ObjectOutputStream是一個高級流, 將 Java 對象的基本數(shù)據(jù)類型和圖形寫入 OutputStream。可以使用 ObjectInputStream 讀取(重構(gòu))對象。通過在流中使用文件可以實(shí)現(xiàn)對象的持久存儲。如果流是網(wǎng)絡(luò)套接字流,則可以在另一臺主機(jī)上或另一個進(jìn)程中重構(gòu)對象。
注意:只能將支持 java.io.Serializable 接口的對象寫入流中。每個 serializable 對象的類都被編碼,編碼內(nèi)容包括類名和類簽名、對象的字段值和數(shù)組值,以及從初始對象中引用的其他所有對象的閉包。
1.1、構(gòu)造函數(shù)
//為完全重新實(shí)現(xiàn) ObjectOutputStream 的子類提供一種方法,讓它不必分配僅由 ObjectOutputStream 的實(shí)現(xiàn)使用的私有數(shù)據(jù)。
protected ObjectOutputStream();
//創(chuàng)建寫入指定 OutputStream 的 ObjectOutputStream。此構(gòu)造方法將序列化流部分寫入底層流;調(diào)用者可以通過立即刷新流,確保在讀取頭部時,用于接收 ObjectInputStreams 構(gòu)造方法不會阻塞。
public ObjectOutputStream(OutputStream out);
1.2、常用的方法
我們這里重點(diǎn)講述的是將一個對象實(shí)例化之后存儲到文件中,其他的write()方法請參看API。
//將指定的對象寫入 ObjectOutputStream。對象的類、類的簽名,以及類及其所有超類型的非瞬態(tài)和非靜態(tài)字段的值都將被寫入。
public final void writeObject(Object obj);
1.2.1、將對象寫入到文件中永久存儲
Person類
import java.io.Serializable;
import java.util.ArrayList;
//Person類實(shí)現(xiàn)了Serializable接口,所以該類才能被序列化;反之,如果沒有實(shí)現(xiàn)該接口的類則不能被序列化。
public class Person implements Serializable{
/**
* 序列化的ID,只要加了該版本號,在反序列化的時候不論你的類的屬性是否改變,只要是版本號不變那么盡經(jīng)可能的兼容新版本。
* 如果版本號改變了,那么反序列化的過程中就會拋出異常。
*/
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對象寫入到文件中
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import tools.Person;
/**
* ObjectOutputStream:高級流,對象輸出流,只能將支持 java.io.Serializable 接口的對象寫入流中
*
* 將一個特定的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為一組字節(jié)的過程稱之為序列化
* 將一組字節(jié)轉(zhuǎn)換為特定的數(shù)據(jù)結(jié)構(gòu)的過程稱之為反序列化
* 將數(shù)據(jù)寫入硬盤長久保存的過程稱之為持久化
*
* @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);
//將一個對象經(jīng)行序列化時需要實(shí)現(xiàn)Serializable接口
oos.writeObject(person);
oos.flush();
oos.close();
System.out.println("對象寫入成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、ObjectInputStream的使用
ObjectInputStream也是一個高級流,對以前使用 ObjectOutputStream 寫入的基本數(shù)據(jù)和對象進(jìn)行反序列化。
2.1、構(gòu)造函數(shù)
//為完全重新實(shí)現(xiàn) ObjectInputStream 的子類提供一種方式,讓它不必分配僅由 ObjectInputStream 的實(shí)現(xiàn)使用的私有數(shù)據(jù)。
protected ObjectInputStream();
//創(chuàng)建從指定 InputStream 讀取的 ObjectInputStream。從流讀取序列化頭部并予以驗(yàn)證。在對應(yīng)的 ObjectOutputStream 寫入并刷新頭部之前,此構(gòu)造方法將阻塞。
public ObjectInputStream(InputStream in);
2.2、常用的方法
我們這里;里主要講述的是將已經(jīng)序列化之后存儲在文件中的對象反序列化的過程,其他的read()方法請參看API。
//從 ObjectInputStream 讀取對象。對象的類、類的簽名和類及所有其超類型的非瞬態(tài)和非靜態(tài)字段的值都將被讀取。
public final Object readObject();
注意看,以上的方法返回的是一個Object,所以我們在反序列化的過程中需要強(qiáng)制轉(zhuǎn)換為我們所需要的類型。
2.2.1、將已經(jīng)序列化的對象反序列化
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import tools.Person;
/**
* ObjectInputStream:高級流,對象輸入流
* ObjectInputStream 對以前使用 ObjectOutputStream 寫入的基本數(shù)據(jù)和對象進(jìn)行反序列化。
* 有支持 java.io.Serializable 或 java.io.Externalizable 接口的對象才能從流讀取。
* @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 一起使用時,可以為應(yīng)用程序提供對對象圖形的持久存儲。ObjectOutputStream用于序列化對象,ObjectInputStream 用于恢復(fù)那些以前序列化的對象(反序列化)。其他用途包括使用套接字流在主機(jī)之間傳遞對象,或者用于編組和解組遠(yuǎn)程通信系統(tǒng)中的實(shí)參和形參。