<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Dict.CN 在線詞典, 英語學習, 在線翻譯

    都市淘沙者

    荔枝FM Everyone can be host

    統(tǒng)計

    留言簿(23)

    積分與排名

    優(yōu)秀學習網(wǎng)站

    友情連接

    閱讀排行榜

    評論排行榜

    java中傳輸對象時候的問題(轉(zhuǎn))

    對于同一個socket,如果調(diào)用兩次就會拋出StreamCorruptedException

    如果你使用socket,并通過對象輸入/輸出流來處理的話,并且已經(jīng)對某個socket調(diào)用了一次getInputStream時,但又需要把這個socket的相關(guān)信息作為參數(shù)傳遞給別的對象時,應(yīng)注意:不用直接把socket傳過去,應(yīng)該把對應(yīng)的ObjectInputStream或ObjectOutputStream對象傳遞過去。

    調(diào)用getInputStream方法就會讀取標示頭信息。用缺省的serializetion的實現(xiàn)時,一個ObjectOutputStream的構(gòu)造和一個ObjectInputStream的構(gòu)造必須一一對應(yīng).ObjectOutputStream的構(gòu)造函數(shù)會向輸出流中寫入一個標識頭,而ObjectInputStream會首先讀入這個標識頭.因此,多次以追加方式向一個文件中寫入object時,該文件將會包含多個標識頭.所以用ObjectInputStream來deserialize這個ObjectOutputStream時,將產(chǎn)生StreamCorruptedException.


    ==============================

    使用ObjectStream會出現(xiàn)的問題

    1. ObjectInputStream與ObjectOutputStream的順序問題
    在網(wǎng)絡(luò)通訊中,主機與客戶端若使用ObjectInputStream與ObjectOutputStream建立對象通訊,必須注意聲明此兩個對象的順序。
    如:
    主機端先建立ObjectInputStream后建立ObjectOutputStream,則對應(yīng)地客戶端要先建立ObjectOutputStream后建立ObjectInputStream,否則會造成兩方互相等待數(shù)據(jù)而導致死鎖。
    原因是建立ObjectInputStream對象是需要先接收一定的header數(shù)據(jù),接收到這些數(shù)據(jù)之前會處于阻塞狀態(tài)。以下為JAVA API文檔的說明
    Creates an ObjectInputStream that reads from the specified InputStream.
    A serialization stream header is read from the stream and verified.
    This constructor will block until the corresponding ObjectOutputStream
    has written and flushed the header.

    故而為了防止這種死鎖狀態(tài),通訊兩方的ObjectInputStraem,ObjectOutputStream必須注意順序?qū)?yīng)使用。

    2. ObjectInputStream接收到非ObjectOutputStream數(shù)據(jù)的問題
    在使用ObjectInputStream與ObjectOutputStream對象通訊的通訊雙方,假設(shè)客戶端程序出現(xiàn)錯誤,發(fā)送了非ObjectOutputStream封裝發(fā)送的數(shù)據(jù)(比如發(fā)送一個數(shù)字或字符串到主機),則主機端的ObjectInputStream接收到錯誤數(shù)據(jù)后不能自動糾正,會一直接收數(shù)據(jù)而處于阻塞狀態(tài),從而導致通訊失敗。尚未找到解決方法。目前想的辦法為寫自己的ObjectStream類。

    3. 解決版本問題
    使用ObjectStream的時候會額外發(fā)送一個關(guān)于對象的序列號
    static final long serialVersionUID = ....
    手動加入此域則可避免版本差異導致的問題。
    對象序列號的計算可用SDK的serialver計算。

    ======================================

    ObjectInputStream ObjectOutputStream

    ObjectOutputStream和ObjectInputStream

    --ObjectOutputStream

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

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

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

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

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

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

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

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

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

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

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

    防止重寫已存在的對象。

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

    然后將序列化類的域從該流中恢復,恢復從最接近 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)序列化接口可以使對象能保存和恢復它的完整狀態(tài),可以使類在寫入流和從流中讀取的期間內(nèi)進行改進。

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

    必須實現(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 方法將負責讀取和恢復這些數(shù)據(jù)。

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

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

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

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

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

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

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

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

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

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


    ObjectOutputStream

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

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

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

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

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

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

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

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

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

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

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

    例如寫入一個對象,此對象能從 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();

    在序列化處理過程中需要特定句柄的類,必須使用如下這些恰當?shù)臉擞泴崿F(xiàn)特定的方法:

    private void readObject(java.io.ObjectInputStream stream)
         throws IOException, ClassNotFoundException;
    private void writeObject(java.io.ObjectOutputStream stream)
         throws IOException

    writeObject 方法負責寫特定類的對象的狀態(tài),以使相應(yīng)的 readObject 方法能存儲它。

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

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

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

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

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

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

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

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

    它們就能使用 ObjectOutput 和 ObjectInput 方法的所有方法寫入或讀取它們自己的狀態(tài)。對象負責管理它出現(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,這就標志著它可以被序列化。

    之后再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 2011-05-17 08:39 都市淘沙者 閱讀(1898) 評論(0)  編輯  收藏 所屬分類: Java Basic/Lucene/開源資料

    主站蜘蛛池模板: 最新亚洲人成无码网站| 精品久久久久久亚洲综合网| a毛片全部免费播放| 亚洲成?Ⅴ人在线观看无码| 亚洲精品无码久久久久秋霞| 亚洲高清视频免费| 亚洲无圣光一区二区| 亚洲黄色免费网站| 亚洲五月综合网色九月色| 日韩av无码成人无码免费| 亚洲视频在线观看2018| 97在线观免费视频观看| 亚洲综合伊人制服丝袜美腿| 皇色在线视频免费网站| 亚洲不卡视频在线观看| 女人被男人桶得好爽免费视频 | 免费国产美女爽到喷出水来视频| 亚洲日韩AV一区二区三区四区| 成人毛片免费在线观看| 国产精品亚洲精品日韩电影| 又黄又爽的视频免费看| 久久国产乱子伦精品免费午夜| 亚洲精品无码久久久久sm| 99爱免费观看视频在线| 亚洲av片不卡无码久久| 国产成人免费手机在线观看视频| 污污视频网站免费观看| 亚洲乱码国产一区三区| 黄色成人免费网站| 亚洲国产精品无码久久| 中文字幕不卡亚洲| 免费黄色网址网站| 羞羞网站在线免费观看| 久久精品国产亚洲夜色AV网站| 台湾一级毛片永久免费| 337P日本欧洲亚洲大胆精品| 国产精品亚洲片在线观看不卡 | 337p日本欧洲亚洲大胆艺术| 成人免费毛片观看| 秋霞人成在线观看免费视频| 亚洲色无码国产精品网站可下载|