网络流中 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的不正确情况。
//将接收到的数据存到字节数组bytes
int 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
{
//
int len = request.getContentLength();
byte buffer[] = new byte[len];
//
InputStream in = request.getInputStream();
int total = 0;
int once = 0;
while ((total < len) && (once >=0)) {
once = in.read(buffer,total,len);
total += once;
}
//
OutputStream 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();
}
}
网络流中 InputStream.available() = 0 问题探究的更多相关文章
- Java中InputStream和String之间的转化
https://blog.csdn.net/lmy86263/article/details/60479350 在Java中InputStream和String之间的转化十分普遍,本文主要是总结一下转 ...
- 从0开始探究vue-组件化-组件之间传值
理解 Vue中有个非常重要的核心思想,就是组件化,组件化是为了代码复用 什么是组件化 组件化,就像一个电脑主机里的主板,有内存条的插口,有硬盘,光驱等等的插口,我们的项目,就像一个电脑主机,通过各种组 ...
- linux中shell变量$#,$@,$0,$1,$2的含义解释
linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行 ...
- win7中VS2010中安装CSS3.0问题解决方法
win7中VS2010中安装CSS3.0问题解决方法 在安装Standards Update for VS2010 SP1后,VS2010中没有CSS3.0问题,以下是我的解决方法 1.首先去官网 ...
- 【原】webapp开发中兼容Android4.0以下版本的css hack
话说现在的手机型号越来越多,主要还是android和ios这2个巨头称霸了江湖,而他们自带的浏览器内核是webkit,那对于做移动网页开发的同事来说,一般只要做好webkit内核浏览器的展现效果就行了 ...
- jquery中$("#afui").get(0)为什么要加get(0)呢?
jquery中$("#afui").get(0)为什么要加get(0)呢? 2015-04-13 17:46SYYZZ3 | 浏览 509 次 Jquery $("#a ...
- C/C++ 中长度为0的数组
参考文献:http://blog.csdn.net/zhaqiwen/article/details/7904515 近日在看项目中的框架代码时,发现了了一个奇特的语法:长度为0的数组例如 uint8 ...
- 在PHP应用中简化OAuth2.0身份验证集成:OAuth 2.0 Client
在PHP应用中简化OAuth2.0身份验证集成:OAuth 2.0 Client 阅读目录 验证代码流程 Refreshing a Token Built-In Providers 这个包能够让你 ...
- linux中shell变量$#,$@,$0,$1,$2的含义解释
linux中shell变量$#,$@,$0,$1,$2的含义解释 linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID ...
随机推荐
- Python——字符串增加颜色
给显示字符添加颜色: salary=int(input('\033[31;1m请输入你的工资:\033[0m')) ('\033[;1m请输入你的工资:\033[0m') 3x是给字符串改变颜色 31 ...
- 大数据之路week07--day06 (Sqoop 将关系数据库(oracle、mysql、postgresql等)数据与hadoop数据进行转换的工具)
为了方便后面的学习,在学习Hive的过程中先学习一个工具,那就是Sqoop,你会往后机会发现sqoop是我们在学习大数据框架的最简单的框架了. Sqoop是一个用来将Hadoop和关系型数据库中的数据 ...
- module method
null 参考链接: https://www.cnblogs.com/lvdabao/p/5953884.html
- 2019-2020-1 20199312《Linux内核原理与分析》第七周作业
进程的描述 操作系统内核实现操作系统的三大管理功能 进程管理(内核中最核心的功能) 内存管理 文件系统 在操作系统中,我们通过进程控制块PCB描述进程. 为了管理进程,内核必须对每个进程进行清晰的描述 ...
- MySQL 索引原理以及慢查询优化
本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree ...
- MYSQL 常见引擎
Mysql常见的引擎 常用的引擎是:Innodb和Myiasm这两种引擎: innodb: 提供了对事务的ACID操作,还提供了行级锁和外键约束,,他的优势就是处理大量数据,在msql启动的时候, ...
- AtomicIntegerFieldUpdater字段原子更新类
本文链接:https://blog.csdn.net/anLA_/article/details/78662383前面讲的两个AtomicInteger和AtomicIntegerArray,这两个都 ...
- bzoj 1072: [SCOI2007]排列perm 状压dp
code: #include <bits/stdc++.h> #define N 1005 using namespace std; void setIO(string s) { stri ...
- 鼠标经过盒子出现边框(伪元素,定位,css3盒子模型)
<body> <div> <img src="mi6.png" > </div> </body> div{ width: ...
- shell脚本之文件操作
文件测试运算符 文件测试运算符用于检测 Unix 文件的各种属性. 下面最常用的是 -f 参数 来检查是否是文件 #!/bin/bash #start nginx php-fpm list1=&quo ...