网络流中 InputStream.available() = 0 问题探究
在处理文件输入流时,通过调用available()方法来获取还有多少字节可以读取,根据该数值创建固定大小的byte数组,从而读取输入流的信息。
FileInputStream fi = new FileInputStream("C:/Users/Administrator/Desktop/yy.txt");//1. read() 逐字节读取 /* int i = 0;byte[] bytes = new byte[fi.available()];while(fi.available() > 0){bytes[i] = (byte) fi.read();i++;}*///2. read(byte b[]) 一次读取byte[] bytes = new byte[fi.available()];fi.read(bytes);fi.close();System.out.println(Arrays.toString(bytes));
但是在处理网络流(socket)时,通过available()方法对输入流进行长度判断,数值为0,这意味着对方发送的流中无数据,但实际上并非如此。
原因在于:
网络通讯往往是间断性的,一串字节往往分几批进行发送。例如对方发来字节长度100的数据,本地程序调用available()方法有时得到0,有时得到50,有时能得到100,大多数情况下是0。这可能是对方还没有响应,也可能是对方已经响应了,但是数据还没有送达本地。也许分3批到达,也许分两批,也许一次性到达。
详细解释参考OSI网络7层结构:
我们进行的数据接收只是基于应用层,网络传输的最上层,数据从一端到另一端传输的时候,会在传输层分解成适合的数据包。传输层(Transport Layer)是OSI 模型中最重要的一层。传输协议同时进行流量控制或是基于接收方可接收数据的快慢程度规定适当的发送速率。除此之外,传输层按照网络能处理的最大尺寸将较长的数据包进行强制分割。例如,以太网无法接收大于1500 字节的数据包。发送方节点的传输层将数据分割成较小的数据片,同时对每一数据片安排一序列号,以便数据到达接收方节点的传输层时,能以正确的顺序重组。该过程即被称为排序。工作在传输层的一种服务是 TCP/IP 协议套中的TCP(传输控制协议),另一项传输层服务是 IPX/SPX 协议集的 SPX(序列包交换)。
InputStream的available()方法的作用是返回此输入流在不受阻塞情况下能读取的字节数。网络流与文件流不同的关键就在于是否“受阻”二字,网络socket流在读取时如果没有内容read()方法是会受阻的,所以从socket初始化的输入流的available也是为零的,所以要read一字节后再使用,这样可用的字节数就等于 available + 1。但文件读取时read()一般是不会受阻的,因为文件流的可用字节数 available = file.length(),而文件的内容长度在创建File对象时就已知了。
所以调用网络流(socket)的available()方法前,一定记得要先调用read()方法,这样才能避免获取为0的不正确情况。
//将接收到的数据存到字节数组bytesint firstByte = inputStream.read();int length = inputStream.available();byte[] bytes = new byte[length+1];bytes[0] = (byte)firstByte;inputStream.read(bytes,1,length);
另外,在文件上载和表单提交的过程中,可以使用 request.getContentLength()方法代替InputStream.available()方法,通过调用 request.getContentLength() 得到 Content-Length ,并定义一个与 Content-Length 大小相等的字节数组 buffer,从HttpServletRequest 的实例 request 中得到一个 InputStream, 并把它读入 buffer 中。然后使用 FileOutputStream 将 buffer 写入指定文件。
// ReceiveServlet.java import java.io.*; import javax.servlet.*; import javax.servlet.http.*; //示例程序:记录下Form提交上来的数据,并存储到Log文件中 public class ReceiveServlet extends HttpServlet {public void doPost(HttpServletRequest request,HttpServletResponse response)throws IOException, ServletException{ //1int len = request.getContentLength();byte buffer[] = new byte[len]; //2InputStream in = request.getInputStream();int total = 0;int once = 0;while ((total < len) && (once >=0)) {once = in.read(buffer,total,len);total += once;} //3OutputStream out=new BufferedOutputStream(new FileOutputStream("Receive.log",true));byte[] breaker="\r\nNewLog: -------------------->\r\n".getBytes();System.out.println(request.getContentType());out.write(breaker,0,breaker.length);out.write(buffer);out.close();} }
转载于:https://www.cnblogs.com/zjfjava/p/10829241.html
网络流中 InputStream.available() = 0 问题探究相关推荐
- Rosserial Arduino Library中从一行代码开始探究系统原理
Rosserial Arduino Library中从一行代码开始探究系统原理 俗话说,管中窥豹,可见一斑. 从一行代码开始,分析rosserial arduino库的脉络.走码观花,到哪儿是哪儿. ...
- 搜索中常见数据结构与算法探究(二)
本文介绍了几个常见的匹配算法,通过算法过程和算法分析介绍了各个算法的优缺点和使用场景,并为后续的搜索文章做个铺垫:读者可以通过比较几种算法的差异,进一步了解匹配算法演进过程以及解决问题的场景:KMP算 ...
- Java中inputStream转字符串
转载:https://blog.csdn.net/lmy86263/article/details/60479350 在Java中InputStream和String之间的转化十分普遍,本文主要是总结 ...
- 【Linux】在VirtualBox-6.0中安装Manjaro18.0
1.参考博客: VMware虚拟机下Manjaro17.1.6安装详细教程 2.在VirtualBox-6.0中安装Manjaro18.0 1)基本步骤和博客中安装17.1.6相同,下面只记录不同的. ...
- 中國web2.0現狀與趨勢調查報告
胡延平:感謝主持人,其實也沒什麼,只不過是我們做了一些Web2.0方面的調查,今天有機會接受邀請來這個地方和大家有一個分享,我來得時間比較晚,但是聽了這麼一會兒我非常的"解渴",在 ...
- numpy中amin()方法中维度axis=0 1 2 的理解
https://www.jianshu.com/p/6f58d7f39147 numpy中amin()方法中维度axis=0 1 2 的理解 axis=0 从最外一层的维度来比较 (对半比较 虽然 ...
- linux中shell变量$#,$@,$0,$1,$2的含义解释
linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $ ...
- 小tips:JS之按位取反,语法标签label,正则表达式中replace的0,1是什么?
JS按位取反 Javascript 按位取反运算符 (~) ,对一个表达式执行位非(求非)运算.如 ~1 = -2; ~2 = -3; 来看看~1的计算步骤: 将1(这里叫:原码)转二进制 = 000 ...
- matlab中,怎样把矩阵中所有的0改为2
一句话搞定:>> a(find(a==0))=[2]:把矩阵中所有的0改为2 转载于:https://www.cnblogs.com/zhizhan/p/3684034.html
- php中的eq的含义,jquery,_jQuery中的eq(0)到底是什么意思??详情请看下面代码!,jquery - phpStudy...
jQuery中的eq(0)到底是什么意思??详情请看下面代码! 手风琴效果 *{padding:0; margin:0;} .box{margin:50px auto; width:300px; he ...
最新文章
- java 小对话框_创建Java对话框
- C++/C++11中头文件iterator的使用
- 技术 | Bengio终结Theano不是偶然,其性能早在Keras支持的四大框架中垫底
- QT的QHashIterator类的使用
- Terraform入门 - 4. destroy 基础设施
- MapReduce-计数器
- m.2接口和nvme区别_透明款散热不好,那么ORICO 全铝NVMe固态硬盘盒了解一下?
- SecureCRT无法登录Ubuntu
- Vue cli3使用jQuery控件
- 在没有图片的情况下用css3实现一个圆形
- android service 本地 远程 总结
- thinkpad10平板 linux,联想ThinkPad 10平板亮相官网 或售8445
- python制作 whl 源文件,并制作本地pip源
- 详解Camtasia的场景转换功能
- 初学Rman 写的备份脚本
- 文章自动采集重新组合工具
- 基于 VEthernet 轻松实现 tun2socks 示例程序
- RFID中的天线技术-应用及设计现状
- MT2601智能穿戴芯片处理器参数介绍
- linux系统中各颜色的代表