java中傳輸對象時候的問題(轉)
對于同一個socket,如果調用兩次就會拋出StreamCorruptedException 如果你使用socket,并通過對象輸入/輸出流來處理的話,并且已經對某個socket調用了一次getInputStream時,但又需要把這個socket的相關信息作為參數傳遞給別的對象時,應注意:不用直接把socket傳過去,應該把對應的ObjectInputStream或ObjectOutputStream對象傳遞過去。 調用getInputStream方法就會讀取標示頭信息。用缺省的serializetion的實現時,一個ObjectOutputStream的構造和一個ObjectInputStream的構造必須一一對應.ObjectOutputStream的構造函數會向輸出流中寫入一個標識頭,而ObjectInputStream會首先讀入這個標識頭.因此,多次以追加方式向一個文件中寫入object時,該文件將會包含多個標識頭.所以用ObjectInputStream來deserialize這個ObjectOutputStream時,將產生StreamCorruptedException.
使用ObjectStream會出現的問題 1. ObjectInputStream與ObjectOutputStream的順序問題 故而為了防止這種死鎖狀態,通訊兩方的ObjectInputStraem,ObjectOutputStream必須注意順序對應使用。 2. ObjectInputStream接收到非ObjectOutputStream數據的問題 3. 解決版本問題 ====================================== ObjectInputStream ObjectOutputStream ObjectOutputStream和ObjectInputStream --ObjectOutputStream ObjectInputStream 類恢復以前使用 ObjectOutputStream 類序列化后的基本類型數據和對象。 ObjectOutputStream 和 ObjectInputStream 分別利用 FileOutputStream 和 FileInputStream 能支持應用程序實現對象圖象的穩定存儲。 ObjectInputStream 可用于恢復以前序列化過的對象。另外其它一些情況也使用此類,諸如使用一個 Socket 在主機間傳遞對象時, 或在遠程通訊系統中為實現參數和參變量的通訊而進行對象傳遞時。 ObjectInputStream 保證從流中創建的圖象中的所有對象的類型與 Java 虛擬機中出現的類匹配。使用標準機制按需裝載相應類。 只有支持 java.io.Serializable 或 java.io.Externalizable 接口的對象才能從流中讀取。使用 readObject 方法從該流中 讀取一個對象。 Java 的安全造型應該用于獲取期望類型。在 Java 中, 串和數組都是對象且可當作是序列化過程中的對象。 讀取時,它們需要轉換為所需類型。 另外基類型也可使用 DataInput 中的正確方法從該流中讀取。 對象的缺省逆序列化機制將每個域的內容恢復為它被寫入時的值和類型。逆序列化過程中忽略申明為暫時的或靜態的域。 對其它對象的引用促使那些對象必須從流中讀取。使用引用共享機制正確地恢復對象的圖象。逆序列化時總是分配新對象, 防止重寫已存在的對象。 讀取一個對象同運行一個新對象的構造子類似。為該對象分配的內存初始化為空(NULL)。為非序列化類調用無參構造子, 然后將序列化類的域從該流中恢復,恢復從最接近 java.lang.object 的序列化對象開始,到指定對象結束。 例如讀取在示例中寫入 ObjectOutputStream 中的流:
實現序列化接口可以使對象能保存和恢復它的完整狀態,可以使類在寫入流和從流中讀取的期間內進行改進。 它自動地遍歷對象間的引用,保存和恢復完整圖象。在序列化和逆序列化處理過程中需要特定句柄的可序列化類, 必須實現如下這兩個方法:
此方法不必關心狀態是屬于它的父類還是子類。 從 ObjectInputStream 讀取數據恢復單個域的狀態,并將之賦給該對象的恰當域。 使用 DataInput 方法讀取基本數據類型。 序列化操作對沒有實現 java.io.Serializable 接口的對象,不讀取或分配它的域值。非序列化對象的子類可以是序列化的。 在這種情況下,非序列化類必須有一個無參構造子,使它的域能使用此構造子完成初始化。 在此情況下, 子類負責保存和恢復非序列化類的狀態。通常情況父類的域是可存儲的(公有的、包或保護的), 或存在用于恢復它的狀態的可使用的獲取或設置方法。 ObjectInputStream 能獲取逆序列化一個對象期間出現的任一異常,一旦出現異常,則放棄讀過程。 實現外部接口可以使對象完全控制此對象序列化形式的內容和格式。 調用外部接口的方法:writeExternal 和 readExternal 保存和恢復對象狀態。當一個類實現了這些方法時, 它們就能使用 ObjectOutput 和 ObjectInput 方法的所有方法寫入或讀取它們自己的狀態。對象負責管理它出現的相應版本。
public class ObjectOutputStream 另外使用此流對應的文件能存儲這些對象。如果該流是一個網絡通訊流,則在另一臺主機或另一個處理機上可重建這些對象。 只有支持 java.io.Serializable 接口的對象才能被寫入該流。對每個可序列化的對象進行編碼,包括相應類的名稱和標記, 對象的屬性和數組值,以及初始化對象時引用的任何其它對象等。 使用 writeObject 將一個對象寫入該流。任一對象,包括串和數組,均采用 writeObject 方法被寫入。 也能將多個對象或基類型對象寫入此流。反過來,必須以這些對象被寫入的相同類型和相同順序, 從相應的 ObjectInputstream 流中讀回這些對象。 基類型也可使用 DataOutput 中的正確方法寫入此流。串對象也可使用 writeUTF 方法寫入。 一個對象的缺省序列化機制將寫入對象的類,類標記和所有的非暫時的和非靜態的屬性值。 其它對象(除暫時的或靜態的屬性)的引用也將促使以上這些對象被寫入。 使用共享機制,對單一對象的多次引用進行編碼, 以至對象的圖元能被存儲為與它原來寫入時有相同的形狀。 例如寫入一個對象,此對象能從 ObjectInputStream 中讀出:
private void readObject(java.io.ObjectInputStream stream) 此方法不必關心寫入對象的父類或子類的狀態。使用 writeObject 方法或基本類型支持的 DataOutput 方法將每個域的狀態保存到 ObjectOutputStream 中。 序列化操作不能輸出沒有實現 java.io.Serializable 接口的任一對象的域。非序列化對象的子類可以是序列化的。 在這種情況下,非序列化類必須有一個無參構造子,使它的域能被初始化。 在此情況下,子類負責保存和恢復非序列化類的狀態。 通常情況父類的域是可存儲的(公有的、包或保護的),或存在用于恢復它的狀態的可使用的獲取或設置方法。 實現拋出 NotSerializableException 異常的 writeObject 和 readObject 方法能阻止一個對象的序列化。 ObjectOutputStream 將獲取這個異常,并放棄這個序列化過程。實現外部接口可以使對象完全控制此對象序列化形式的內容和格式。 調用外部接口的方法:writeExternal 和 readExternal 保存和恢復對象狀態。當一個類實現了這些方法時, 它們就能使用 ObjectOutput 和 ObjectInput 方法的所有方法寫入或讀取它們自己的狀態。對象負責管理它出現的相應版本。
public class Logon implements Serializable { private Date date = new Date();
int seconds = 5; ObjectInputStream in = new ObjectInputStream( new FileInputStream("Logon.out")); 類Logon是一個記錄登錄信息的類,包括用戶名和密碼。首先它實現了接口Serializable,這就標志著它可以被序列化。 之后再main方法里ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream("Logon.out")); 新建一個對象輸出流包裝一個文件流,表示對象序列化的目的地是文件Logon.out。然后用方法writeObject開始寫入。 想要還原的時候也很簡單ObjectInputStream in = new ObjectInputStream( new FileInputStream("Logon.out")); 新建一個對象輸入流以文件流Logon.out為參數,之后調用readObject方法就可以了。 |
posted on 2011-05-17 08:39 都市淘沙者 閱讀(1892) 評論(0) 編輯 收藏 所屬分類: Java Basic/Lucene/開源資料