转载:https://blog.csdn.net/lilidejing/article/details/37913627

当需要用到InputStream获取数据时,这时就需要读取InputStream里面的数据了。

InputStream读取流有三个方法,分别为read(),read(byte[] b),read(byte[] b, int off, int len)。在从数据流里读取数据时,为图简单,经常用InputStream.read()方法。这个方法是从流里每次只读取读取一个字节,效率会非常低。更好的方法是用InputStream.read(byte[] b)或者InputStream.read(byte[] b,int off,int len)方法,一次读取多个字节。但是这些方法都不能一次性把流中的数据读取完整或不知道有没有读取完整。

遇到上面这个问题,网上有人提出用InputStream.available()方法,这个方法可以在读写操作前先得知数据流里有多少个字节可以读取。需要注意的是,如果这个方法用在从本地文件读取数据时,一般不会遇到问题,但如果是用于网络操作,就经常会遇到一些麻烦。这是因为网络通讯往往是间断性的,一串字节往往分几批进行发送。例如对方发来字节长度100的数据,本地程序调用available()方法有时得到0,有时得到50,有时能得到100,大多数情况下是100。这可能是对方还没有响应,也可能是对方已经响应了,但是数据还没有送达本地。也许分3批到达,也许分两批,也许一次性到达。

如果按下面写,可能就会出错,因为会出现上面说的情况:

int count = in.available();
byte[] b = new byte[count];
in.read(b);
  于是网上有人提议改成下面那样:

int count = 0;
while (count == 0) {
count = in.available();
}
byte[] b = new byte[count];
in.read(b);
       甚至接着提出下面的方法配合着上面用:

byte[] b = new byte[count];
int readCount = 0; // 已经成功读取的字节的个数
while (readCount < count) {
readCount += in.read(bytes, readCount, count - readCount);
}
        之所以用下面的这段代码可以保证读取count个字节,因为前面说了,read方法读取不到自己想要读取的个数的字节。下面的这段代码没问题,但是上面的那段就有问题了。while循环里面条件搞成count==0,很明显,有时数据分两批发过来时,假如100的数据第一批是20,第二批是80,那下面的方法就只能读取20了,还是不完整啊。也许一时测试没什么问题,但是你InputStream接收数据太快或频繁,这样问题就出来了。
    我是真遇到上面说的问题了,最后的解决办法是:

先说下解决思路:接到第一份数据的时候等待0.2秒,之后完整的数据应该会全部发过来。

byte[] b= new byte[1024];
int count = 0;
if(inputStream.available()>0 == false){
continue;
}else{
Thread.sleep(200);
}
count = inputStream.read(b);
      出现分段过来的时候:第一次inputStream.available()可能为20,但是休眠0.2秒过后执行count=inputStream.read(b);时,输入流应该很完整了,而且不像分成两段时候执行了两次缺失输入流,这里虽然数据是分两段发过来的,但是sleep后面的代码只会执行一次。如果你怕休眠0.2秒时间短接收不完全,可以设置成0.3或0.5。目前我用的这种方法,数据一直能读取完全。
————————————————

另外在实际项目用到的

byte[] readBuffer = new byte[1024];
int numBytes = -1;
ByteArrayOutputStream result = new ByteArrayOutputStream(); try {
while (inputStream.available() > 0) {
numBytes = inputStream.read(readBuffer);
if (numBytes >= 0) {
result.write(readBuffer, 0, numBytes);
readBuffer = new byte[1024];
Thread.sleep(500);
}
} String out = new String(result.toByteArray(), "UTF-8");

最新文章

  1. css-display:none和visibility:hidden的不同
  2. ASP.NET WEB API路由机制
  3. https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform
  4. CodeForces 686C-Robbers&#39; watch
  5. 实现快速迭代的引擎设计 - Capcom RE Engine的架构与实现
  6. 20160805_Win7x64刻录CentOS6.4x64启动光盘
  7. centos6.4下安装freetds使php支持mssql
  8. 关于 hashCode() 你需要了解的 3 件事
  9. Calendar中add函数和roll函数的用法及区别
  10. FastJson中@JSONField注解使用
  11. 省份、城市、区县三级联动Html代码
  12. 有向图的邻接矩阵表示法(创建,DFS,BFS)
  13. .Net程序员面试试题
  14. OPENFILENAME使用lpstrFilter过滤文件类型
  15. 201521123070 《JAVA程序设计》第3周学习总结
  16. C++获取基类指针所指子类对象的类名
  17. h5笔记02
  18. iOS UI基础-21 WKWebView
  19. 王之泰201771010131《面向对象程序设计(java)》第八周学习总结
  20. sed原理及使用

热门文章

  1. AttnGAN: Fine-Grained Text to Image Generation with Attentional Generative Adversarial Networks 笔记
  2. MongoDB部分
  3. PLSQL Developer、汉化包官方下载及注册码
  4. Django-redis配置cache和session
  5. 轻松搭建CAS 5.x系列(8)-在CAS Server增加双因素认证(DUO版)
  6. ORACLE:锁被未决分布式事务处理 18.27.160617 持有
  7. UIApplicationDelegate里面最常用的几个函数执行顺序小结
  8. 在nuxt中引入Font Awesome字体图标库
  9. 为什么Java大数据能带你走上人生巅峰
  10. 《python解释器源码剖析》第13章--python虚拟机中的类机制