2012-05-26 58 views
0

我在一個客戶端/服務器聊天應用程序,它允許用戶通過套接字連接發送文件(圖像/視頻...)工作。在Java中的文件傳輸和對象序列化

爲了管理所有類型的通信,我使用一個對象「數據包」,它存儲了我想發送的所有信息。 (發件人,收件人,文件...)。

這裏是我在流中寫一個代碼示例:

private void write(Packet packet) throws IOException { 
    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
    ObjectOutputStream os = new ObjectOutputStream(bos); 
    os.writeObject(packet); 
    this.outStream.write(bos.toByteArray()); 
} 

而且outStream是一個OutputStream。

這是我連接上運行:

public void run() { 
    while (isRunning()) { 
     try { 
      byte[] buffer = new byte[65536]; 
      // Read from the InputStream 
      inStream.read(buffer); 
      ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer)); 
      Packet p = (Packet) in.readObject(); 

     } catch (IOException e) { 
      e.printStackTrace(); 
      this.disconnect(); 
     } 
    } 
} 

它非常適用於除了文件傳輸的所有目的! 我把文件放在一個字節[](帶有文件流)並將數組存儲在我的數據包對象中。 當服務器收到通信時,它會在「in.readObject()」中斷開,並給我一個漂亮的「java io streamcorruptedexception錯誤格式:0」異常。

我嘗試使用自定義字節[](由string.getBytes()填充)進行傳輸,並且它工作得很好。

那麼,我做錯了什麼?

回答

3

您正在從InputStream讀取一個字節數組(任意大小可能太小)。然後你構造一個ObjectInputStream來讀取這個字節數組。爲什麼不直接從InputStream讀取對象?

ObjectInputStream in = new ObjectInputStream(inStream); 
Packet p = (Packet) in.readObject(); 

不需要緩衝區。

此外,InputStream.read()不會讀取InputStream中的所有內容。它讀取可用的內容,並返回讀取的字節數。如果你不循環,直到它返回-1,你只能讀取另一邊發送的內容的一部分。

順便說一句,你在發送方犯了同樣的錯誤。不是直接將對象寫入輸出流,而是將其寫入一個字節數組,然後發送該字節數組。將您的對象直接寫入流中:

ObjectOutputStream os = new ObjectOutputStream(this.outputStream); 
os.writeObject(packet); 

不需要緩衝區。

+0

謝謝。很棒。這裏是我現在運行的樣子: 'ObjectInputStream in = new ObjectInputStream(inStream); (in.read()!= -1) } 數據包p =(數據包)in.readObject();' – LukeS

+1

您不需要循環。如果您讀取字節(您在原始代碼中執行的操作),這是必要的。如果讀取Object,則ObjectInputStream將根據需要讀取儘可能多的字節,以返回字節流中的第一個對象。 –