在处理文件输入流时,通过调用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();
}
}

最新文章

  1. 千万pv大型web系统架构,学习从点滴开始
  2. Android 面试题--Activity
  3. vs.net Web.csproj.webinfo文件
  4. 【推荐】【给中高级开发者】构建高性能ASP.NET应用的几点建议
  5. 转载:Objective-C中的 instancetype 和 id 关键字
  6. css盒子模型层级3D图
  7. linux的命令(1)
  8. STL六大组件之——适配器代表大会
  9. 三款精美的html5及css3的源码插件
  10. 九度OJ 城际公路网 -- 图论
  11. WINDOWS BITLOCK
  12. Django学习(四) Django提供的后台管理系统以及如何定义URL路由
  13. poj2774之最长公共子串
  14. jdb 调试
  15. Unity3D拖尾组件在Ui界面下正常显示
  16. 设计模式 --&gt; (8)组合模式
  17. [深度应用]&#183;首届中国心电智能大赛初赛开源Baseline(基于Keras val_acc: 0.88)
  18. mysql 创建备份表
  19. LVM-COW写实备份
  20. K8s之配置文件kubeconfig生成

热门文章

  1. Linux环境变量$PATH
  2. docker部署Redmine项目管理平台
  3. flutter入门开发的一些坑
  4. chrome DevTools功能介绍
  5. JVM的深入理解:由一次Quartz的定时任务引发的“A cannot cast to A”的问题
  6. Kotlin扩展深入解析及注意事项和可见性
  7. 学习markdown(一)
  8. 07 c++中的内联函数inline
  9. 编程判断输入的字符是否为‘y’或‘Y’,若是,则输出‘yes’,否则输出‘no’
  10. ElementUI入门和NodeJS环境搭建