2015-04-28 26 views
0

考虑我们在两个设备(A和B)之间有套接字连接。现在,如果我只写16个字节(大小并不重要,在这里)在侧插座的输出流(未的BufferedOutputStream)A 3倍或一般不止一次这样:java套接字是否按照发送的数据完全读取数据

OutputStream outputStream = socket.getOutputStream(); 
byte[] buffer = new byte[16]; 
OutputStream.write(buffer); 
OutputStream.write(buffer); 
OutputStream.write(buffer); 

我读了使用套接字输入流(未的BufferedInputStream)与除例如1024发送缓冲区大的缓冲器在B侧数据:

InputStream inputStream = socket.getInputStream(); 
byte[] buffer = new byte[1024]; 
int read = inputStream.read(buffer); 

现在我不知道如何将数据B侧接收?可能会累积起来,还是完全读取A发送的数据?换句话说,读取变量可能会超过16?

+2

这一切都取决于时间。如果B在尝试读取时已收到所有输入,则它将读取全部16 * 3个字节。但是,如果到那时候只有其中一个或两个被发送,它将只能读取那些。 – Jon

+0

如何在发送之前开始阅读? @Jon – Ali

+1

@Ali:此方法阻塞,直到输入数据可用,检测到文件结尾或抛出异常。 – Anton

回答

2

InputStream对通过调用多字节方法读取多少数据的保证很少。有一整类常见的编程错误都是围绕着误解和错误假设而产生的。例如,

  • InputStream.read(byte[])如果读取比提供的数组可容纳更少的字节,这并不意味着流的末尾已经达到,或甚至另一读取将必然阻止。
  • 任何一次调用InputStream.read(byte[])所读取的字节数并不一定与流所绘制的字节源的任何特性相关,除非它不会在流结束时读取至少一个字节,并且它不会读取比它返回时实际可用的字节更多的字节。
  • available()方法指示的可用字节数不能可靠地指示后续读取应读取或将读取的字节数。非零返回值可靠地表示下一次读取不会被阻止;零返回值告诉你什么都没有

子类可能会对这些行为中的某些行为做出保证,但大多数行为都不会,并且无论如何,您通常不知道您实际拥有哪个子类。

为了正确使用InputStream,您通常必须准备好重复读取,直到您获得足够的数据进行处理。这可能意味着读取,直到您累积了特定数量的字节,或读取直到遇到分隔符为止。在某些情况下,您可以处理任何给定读取中的任意数量的字节;通常情况下,这些都是你正在循环的情况,并且将你读的所有内容都提供给可以接受可变长度块的消费者(例如许多压缩和加密接口就是这样)。

1

每文档:

public int read(byte[] b) throws IOException 

读取从输入流中,并将它们存储到缓冲区数组b一定数量的字节。实际读取的字节数 以整数形式返回。此方法阻止,直到 输入数据可用,检测到文件结尾或抛出异常 。如果b的长度为零,则不读取字节,并且返回0为 ;否则,尝试读取至少一个字节。如果 没有字节可用,因为该流在文件末尾,则返回值 ;否则,至少读取一个字节并将 存储到b中。

将读取的第一个字节存储到元素b [0]中,将下一个字节存储到 b [1]中,依此类推。读取的字节数最多等于b的长度为 。令k为实际读取的字节数;这些字节 将存储在元素b [0]至b [k-1],中,从而保持元素b [k] 至b [b.length-1]不受影响

Read(...)告诉你有多少字节放入数组中,是的,你可以进一步阅读;你会得到任何已经存在的东西。