2012-05-26 60 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将根据需要读取尽可能多的字节,以返回字节流中的第一个对象。 –