关于InputStream 中available()方法的使用问题


在用流进行数据或文件读写的时候经常看到某些人会使用下面的固定字节长度的数组,存储InputStream 读取的字节

常见代码如下:

       in = new ByteArrayInputStream(postData.getBytes(charSet));
       byte[] buf = new byte[1024];
       int len;
       while ((len = in.read(buf)) > 0) {
	   out.write(buf, 0, len);
       }
那么会有一个疑问1024长度是怎嘛来的?如果InputStream 流长度超过1024,岂不是会造成读取部分的问题,针对这个问题我有比较深刻的体会,第一次 出现读取失败的问题,然后自己就将1024改为2048...等等一直扩展,扩展的时候在想难道InputStream 没有提供这样的一个方法吗?返回我要读取的字节长度,翻阅API,百度,看了大部分同事都是用的InputStream 的available()方法。

看一下官方API解释:

public int available() throws IOException


返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。下一个调用可能是同一个线程,也可能是另一个线程。一次读取或跳过此估计数个字节不会受阻塞,但读取或跳过的字节数可能小于该数。

注意,有些 InputStream 的实现将返回流中的字节总数,但也有很多实现不会这样做。试图使用此方法的返回值分配缓冲区,以保存此流所有数据的做法是不正确的

如果已经调用 close() 方法关闭了此输入流,那么此方法的子类实现可以选择抛出IOException

InputStreamavailable 方法总是返回 0

此方法应该由子类重写

返回:可以不受阻塞地从此输入流读取(或跳过)的估计字节数;如果到达输入流末尾,则返回 0;


所以调用此方法的时候,首先查看实现类有没有实现此方法。


我以为这样就完事了。

若干月后我要获取网络流但发现获取的available()返回的长度为“0” !!!

很疑惑为什吗是这样的呢?不会就问度娘!发现很多人也遇到了同样的问题,解释如下:

因为网络通讯往往是间断性的,一串字节往往分几批进行发送。例如对方发来字节长度100的数据,本地程序调用available()方法有时得到0,有时得到50,有时能得到100,大多数情况下是100。这可能是对方还没有响应,也可能是对方已经响应了,但是数据还没有送达本地。也许分3批到达,也许分两批,也许一次性到达。

所以如果直接使用 available()方法就会出错。难道就没有好的解决方案吗?

目前网上给出了如下两种解决方式:

1、调用available()方法之前让线休眠0.2~0.5秒Threed.sheep(200)

2、获取报文传输参数Content-length的长度。

目前觉得方法2比较合理!附上IBM使用此方法的例子 http://www.ibm.com/developerworks/cn/java/fileup/


可能很多人到此出就结束了,但一直有一个问题萦绕在我脑海,那就是为什么网络通讯是间断性的?

寻根究底,最后想可能是网络传输发包的原因,于是就去看了OSI网络7层模型,我们进行的数据接收只是基于应用层,网络传输的最上层,

关于InputStream 中available()方法的使用问题_第1张图片

数据从一端到另一端传输的时候,会在传输层分解成适合的数据包,看下官方解释

传输层(Transport Layer)

O S I 模型中最重要的一层。传输协议同时进行流量控制或是基于接收方可接收数据的快慢程度规定适当的发送速率。除此之外,传输层按照网络能处理的最大尺寸将较长的数据包进行强制分割。例如,以太网无法接收大于1 5 0 0 字节的数据包。发送方节点的传输层将数据分割成较小的数据片,同时对每一数据片安排一序列号,以便数据到达接收方节点的传输层时,能以正确的顺序重组。该过程即被称为排序。 工作在传输层的一种服务是 T C P / I P 协议套中的T C P (传输控制协议),另一项传输层服务是I P X / S P X 协议集的S P X (序列包交换)


疑问:数据包什吗时候发送完毕?

你可能感兴趣的:(JavaSE)