Mark's Java Blog
          MyEclipse, Java EE, Spring, Struts, Hibernate, JPA, SWT, Swing, AJAX, JavaScript,SOA

          ObjectOutputStream和ObjectInputStream

          --ObjectOutputStream

          ObjectInputStream 類恢復(fù)以前使用 ObjectOutputStream 類序列化后的基本類型數(shù)據(jù)和對象。

          ObjectOutputStream 和 ObjectInputStream 分別利用 FileOutputStream 和 FileInputStream 能支持應(yīng)用程序?qū)崿F(xiàn)對象圖象的穩(wěn)定存儲。

          ObjectInputStream 可用于恢復(fù)以前序列化過的對象。另外其它一些情況也使用此類,諸如使用一個 Socket 在主機(jī)間傳遞對象時,

          或在遠(yuǎn)程通訊系統(tǒng)中為實現(xiàn)參數(shù)和參變量的通訊而進(jìn)行對象傳遞時。

          ObjectInputStream 保證從流中創(chuàng)建的圖象中的所有對象的類型與 Java 虛擬機(jī)中出現(xiàn)的類匹配。使用標(biāo)準(zhǔn)機(jī)制按需裝載相應(yīng)類。

          只有支持 java.io.Serializable 或 java.io.Externalizable 接口的對象才能從流中讀取。使用 readObject 方法從該流中

          讀取一個對象。 Java 的安全造型應(yīng)該用于獲取期望類型。在 Java 中, 串和數(shù)組都是對象且可當(dāng)作是序列化過程中的對象。

          讀取時,它們需要轉(zhuǎn)換為所需類型。

          另外基類型也可使用 DataInput 中的正確方法從該流中讀取。

          對象的缺省逆序列化機(jī)制將每個域的內(nèi)容恢復(fù)為它被寫入時的值和類型。逆序列化過程中忽略申明為暫時的或靜態(tài)的域。

          對其它對象的引用促使那些對象必須從流中讀取。使用引用共享機(jī)制正確地恢復(fù)對象的圖象。逆序列化時總是分配新對象,

          防止重寫已存在的對象。

          讀取一個對象同運行一個新對象的構(gòu)造子類似。為該對象分配的內(nèi)存初始化為空(NULL)。為非序列化類調(diào)用無參構(gòu)造子,

          然后將序列化類的域從該流中恢復(fù),恢復(fù)從最接近 java.lang.object 的序列化對象開始,到指定對象結(jié)束。

          例如讀取在示例中寫入 ObjectOutputStream 中的流:


           FileInputStream istream = new FileInputStream("t.tmp");
           ObjectInputStream p = new ObjectInputStream(istream);
           int i = p.readInt();
           String today = (String)p.readObject();
           Date date = (Date)p.readObject();
           istream.close();
           
          類通過實現(xiàn) java.io.Serializable 或 java.io.Externalizable 接口來控制它們的序列化。

          實現(xiàn)序列化接口可以使對象能保存和恢復(fù)它的完整狀態(tài),可以使類在寫入流和從流中讀取的期間內(nèi)進(jìn)行改進(jìn)。

          它自動地遍歷對象間的引用,保存和恢復(fù)完整圖象。在序列化和逆序列化處理過程中需要特定句柄的可序列化類,

          必須實現(xiàn)如下這兩個方法:


           private void writeObject(java.io.ObjectOutputStream stream)
               throws IOException;
           private void readObject(java.io.ObjectInputStream stream)
               throws IOException, ClassNotFoundException;
           
          利用 writeObjectmethod 方法將一個特殊類的對象的狀態(tài)寫入某流后,相應(yīng)的 readObject 方法將負(fù)責(zé)讀取和恢復(fù)這些數(shù)據(jù)。

          此方法不必關(guān)心狀態(tài)是屬于它的父類還是子類。 從 ObjectInputStream 讀取數(shù)據(jù)恢復(fù)單個域的狀態(tài),并將之賦給該對象的恰當(dāng)域。

          使用 DataInput 方法讀取基本數(shù)據(jù)類型。

          序列化操作對沒有實現(xiàn) java.io.Serializable 接口的對象,不讀取或分配它的域值。非序列化對象的子類可以是序列化的。

          在這種情況下,非序列化類必須有一個無參構(gòu)造子,使它的域能使用此構(gòu)造子完成初始化。 在此情況下,

          子類負(fù)責(zé)保存和恢復(fù)非序列化類的狀態(tài)。通常情況父類的域是可存儲的(公有的、包或保護(hù)的),

          或存在用于恢復(fù)它的狀態(tài)的可使用的獲取或設(shè)置方法。

          ObjectInputStream 能獲取逆序列化一個對象期間出現(xiàn)的任一異常,一旦出現(xiàn)異常,則放棄讀過程。

          實現(xiàn)外部接口可以使對象完全控制此對象序列化形式的內(nèi)容和格式。

          調(diào)用外部接口的方法:writeExternal 和 readExternal 保存和恢復(fù)對象狀態(tài)。當(dāng)一個類實現(xiàn)了這些方法時,

          它們就能使用 ObjectOutput 和 ObjectInput 方法的所有方法寫入或讀取它們自己的狀態(tài)。對象負(fù)責(zé)管理它出現(xiàn)的相應(yīng)版本。


          ObjectOutputStream

          public class ObjectOutputStream
          extends OutputStream
          implements ObjectOutput, ObjectStreamConstants
          類 ObjectOutputStream 將 Java 對象中的基本數(shù)據(jù)類型和圖元寫入到一個 OutputStream 對象中。可使用 ObjectInputStream 讀取這些對象。

          另外使用此流對應(yīng)的文件能存儲這些對象。如果該流是一個網(wǎng)絡(luò)通訊流,則在另一臺主機(jī)或另一個處理機(jī)上可重建這些對象。

          只有支持 java.io.Serializable 接口的對象才能被寫入該流。對每個可序列化的對象進(jìn)行編碼,包括相應(yīng)類的名稱和標(biāo)記,

          對象的屬性和數(shù)組值,以及初始化對象時引用的任何其它對象等。

          使用 writeObject 將一個對象寫入該流。任一對象,包括串和數(shù)組,均采用 writeObject 方法被寫入。

          也能將多個對象或基類型對象寫入此流。反過來,必須以這些對象被寫入的相同類型和相同順序,

          從相應(yīng)的 ObjectInputstream 流中讀回這些對象。

          基類型也可使用 DataOutput 中的正確方法寫入此流。串對象也可使用 writeUTF 方法寫入。

          一個對象的缺省序列化機(jī)制將寫入對象的類,類標(biāo)記和所有的非暫時的和非靜態(tài)的屬性值。

          其它對象(除暫時的或靜態(tài)的屬性)的引用也將促使以上這些對象被寫入。 使用共享機(jī)制,對單一對象的多次引用進(jìn)行編碼,

          以至對象的圖元能被存儲為與它原來寫入時有相同的形狀。

          例如寫入一個對象,此對象能從 ObjectInputStream 中讀出:


           FileOutputStream ostream = new FileOutputStream("t.tmp");
           ObjectOutputStream p = new ObjectOutputStream(ostream);
           p.writeInt(12345);
           p.writeObject("Today");
           p.writeObject(new Date());
           p.flush();
           ostream.close();
           
          在序列化處理過程中需要特定句柄的類,必須使用如下這些恰當(dāng)?shù)臉?biāo)記實現(xiàn)特定的方法:

           private void readObject(java.io.ObjectInputStream stream)
               throws IOException, ClassNotFoundException;
           private void writeObject(java.io.ObjectOutputStream stream)
               throws IOException
           
          writeObject 方法負(fù)責(zé)寫特定類的對象的狀態(tài),以使相應(yīng)的 readObject 方法能存儲它。

          此方法不必關(guān)心寫入對象的父類或子類的狀態(tài)。使用 writeObject 方法或基本類型支持的 DataOutput

          方法將每個域的狀態(tài)保存到 ObjectOutputStream 中。

          序列化操作不能輸出沒有實現(xiàn) java.io.Serializable 接口的任一對象的域。非序列化對象的子類可以是序列化的。

          在這種情況下,非序列化類必須有一個無參構(gòu)造子,使它的域能被初始化。 在此情況下,子類負(fù)責(zé)保存和恢復(fù)非序列化類的狀態(tài)。

          通常情況父類的域是可存儲的(公有的、包或保護(hù)的),或存在用于恢復(fù)它的狀態(tài)的可使用的獲取或設(shè)置方法。

          實現(xiàn)拋出 NotSerializableException 異常的 writeObject 和 readObject 方法能阻止一個對象的序列化。

          ObjectOutputStream 將獲取這個異常,并放棄這個序列化過程。實現(xiàn)外部接口可以使對象完全控制此對象序列化形式的內(nèi)容和格式。

          調(diào)用外部接口的方法:writeExternal 和 readExternal 保存和恢復(fù)對象狀態(tài)。當(dāng)一個類實現(xiàn)了這些方法時,

          它們就能使用 ObjectOutput 和 ObjectInput 方法的所有方法寫入或讀取它們自己的狀態(tài)。對象負(fù)責(zé)管理它出現(xiàn)的相應(yīng)版本。


          import java.io.*;
          import java.util.*;

          public class Logon implements Serializable {

                 private Date date = new Date();
                 private String username;
                 private transient String password;


                 Logon(String name, String pwd) {
                        username = name;
                        password = pwd;
                 }


                 public String toString() {
                        String pwd = (password == null) ? "(n/a)" : password;
                        return "logon info: \n " + "username: " + username + "\n date: " + date + "\n password: " + pwd;
                 }


                 public static void main(String[] args) throws IOException, ClassNotFoundException {
                        Logon a = new Logon("Morgan", "morgan83");
                        System.out.println( "logon a = " + a);
                        ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream("Logon.out"));
                        o.writeObject(a);
                        o.close();

                        int seconds = 5;
                        long t = System.currentTimeMillis() + seconds * 1000;
                        while(System.currentTimeMillis() < t) ;

                        ObjectInputStream in = new ObjectInputStream( new FileInputStream("Logon.out"));
                        System.out.println( "Recovering object at " + new Date());
                        a = (Logon)in.readObject();
                        System.out.println("logon a = " + a);
                 }
          }
           

          類Logon是一個記錄登錄信息的類,包括用戶名和密碼。首先它實現(xiàn)了接口Serializable,這就標(biāo)志著它可以被序列化。

          之后再main方法里ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream("Logon.out"));

          新建一個對象輸出流包裝一個文件流,表示對象序列化的目的地是文件Logon.out。然后用方法writeObject開始寫入。

          想要還原的時候也很簡單ObjectInputStream in = new ObjectInputStream( new FileInputStream("Logon.out"));

          新建一個對象輸入流以文件流Logon.out為參數(shù),之后調(diào)用readObject方法就可以了。

           

          posted on 2008-04-14 13:53 Mark 閱讀(1242) 評論(0)  編輯  收藏 所屬分類: Java SE
           
          主站蜘蛛池模板: 宝应县| 铅山县| 拜泉县| 八宿县| 全州县| 巴彦县| 巫山县| 青河县| 江西省| 南开区| 承德县| 朝阳市| 海林市| 东丰县| 乡宁县| 牙克石市| 南康市| 肥城市| 舒兰市| 斗六市| 昭平县| 莱西市| 稷山县| 宁南县| 丰县| 轮台县| 建阳市| 巧家县| 怀远县| 澄江县| 二连浩特市| 乐清市| 洛隆县| 页游| 庆元县| 思茅市| 晋宁县| 青铜峡市| 曲阳县| 巴林左旗| 秦皇岛市|