2014-02-07 77 views
6

我想使用單個ObjectInputStream從字節數組中讀取數據,但每次啓動程序時都會收到StreamCorruptedException。ObjectInputStream無效的數據頭:00000000

public void run(){ 

     byte[] receiveBuffer = new byte[65535]; 

     bIn = new ByteArrayInputStream(receiveBuffer); 

     try { 
      in = new ObjectInputStream(bIn); 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 

     while(true){ 
      try { 
       packetIn = new DatagramPacket(receiveBuffer, receiveBuffer.length); 
       sock.receive(packetIn); 

       Object o = in.readObject(); 
       //do things with o 
      } 
     } 
} 

我只是試圖初始化ObjectInputStream最終從字節數組中讀取,但即使我刪除了while循環,它仍然拋出該異常。

我在這裏做錯了什麼?

回答

6

如果你看一看的Javadoc,ObjectInputStream(InputStream)構造函數,你會看到:

創建一個ObjectInputStream中讀取自指定的InputStream。 從流中讀取序列化流頭並進行驗證。該構造函數將阻塞,直到相應的ObjectOutputStream寫入並刷新標題。

...

拋出

        StreamCorruptedException - 如果該流報頭是不正確

(強調)

換句話說,構造沒有按」 t只需記錄你給它的參考文獻InputStream,它也讀取那個o bject。在這種情況下,這是所有0 s的流。

你應該推遲創建ObjectInputStream,直到你有序列化的數據(或者至少有足夠的它來讀取頭文件)。爲了「教人釣魚」,我還會注意到,只要方法/構造函數拋出一個你並不期望的異常,那麼該方法的javadocs就是開始理解它的好地方JDK類的javadoc通常都不錯)

+0

所以你說使用套接字輸入流,並收集所有字節進來閱讀,然後創建對象輸入流來讀取字節並獲取對象?它是否正確?基本上緩衝它呢? –

+0

這是一個解決方案。另一種是在流準備好讀取之前不創建讀取器。 – yshavit

2

流協議包含一個流頭,其中ObjectInputStream讀入構造函數。您必須在您收到的東西推遲創建流:

sock.receive(packetIn); 

    try { 
     in = new ObjectInputStream(bIn); 
     Object o = in.readObject(); 
    } catch (IOException e1) { 
     e1.printStackTrace(); 
    } 
2

好的,這就是對象流的工作原理和解決方案,它可以在任何地方工作。

對象流數據前面有一個4字節的「神奇」序列AC ED 00 05.一個ObjectInputStream將在施工時查看這些數據,而不是在第一次讀取之前。這是合乎邏輯的:在應用程序太遠之前,要確定它是一個合適的流。該序列在構建時被ObjectOutputStream緩衝,以便在第一次寫入時將其推入流中。此方法通常會導致緩衝情況下的複雜性或通過管道或套接字進行傳輸。幸運的是,對於所有這些問題,有效的解決方案同樣簡單:

施工後立即刷新ObjectOutputStream!

ObjectOutputStream myStream = new ObjectOutputStream (anotherStream); 
myStream.flush(); 

在你的情況,你將不得不使用一個的ObjectOutputStream,如果你想從ObjectInputStream

+0

myStream.flush();爲我工作..謝謝 –

+0

你是什麼意思由anotherStream? –

相關問題