转载: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");

解决InputStream中数据读取不完整问题的更多相关文章

  1. 如何解决wamp中数据库读取数据是???的情况?

    数据库中数据正常,但是从数据库读取出的数据在网页中显示时是???,该怎么办呢? 左键点击托盘区的WampServer图标,选择Mysql--my.ini,就会打开配置文件 1.在[client]段落增 ...

  2. 3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案

    根据之前解析的循环依赖的源码, 分析了一级缓存,二级缓存,三级缓存的作用以及如何解决循环依赖的. 然而在多线程的情况下, Spring在创建bean的过程中, 可能会读取到不完整的bean. 下面, ...

  3. BlockingQueue阻塞队列(解决多线程中数据安全问题 可用于抢票,秒杀)

    案例:一个线程类中 private static BlockingQueue<Map<String, String>> dataQueue = new LinkedBlocki ...

  4. TensorFlow中数据读取之tfrecords

    关于Tensorflow读取数据,官网给出了三种方法: 供给数据(Feeding): 在TensorFlow程序运行的每一步, 让Python代码来供给数据. 从文件读取数据: 在TensorFlow ...

  5. 解决Redis中数据不一致问题

    redis系列之数据库与缓存数据一致性解决方案 数据库与缓存读写模式策略写完数据库后是否需要马上更新缓存还是直接删除缓存? (1).如果写数据库的值与更新到缓存值是一样的,不需要经过任何的计算,可以马 ...

  6. TensorFlow中数据读取—如何载入样本

    考虑到要是自己去做一个项目,那么第一步是如何把数据导入到代码中,何种形式呢?是否需要做预处理?官网中给的实例mnist,数据导入都是写好的模块,那么自己的数据呢? 一.从文件中读取数据(CSV文件.二 ...

  7. Spark(十二)【SparkSql中数据读取和保存】

    一. 读取和保存说明 SparkSQL提供了通用的保存数据和数据加载的方式,还提供了专用的方式 读取:通用和专用 保存 保存有四种模式: 默认: error : 输出目录存在就报错 append: 向 ...

  8. 从零搭建Pytorch模型教程(一)数据读取

    ​  前言  本文介绍了classdataset的几个要点,由哪些部分组成,每个部分需要完成哪些事情,如何进行数据增强,如何实现自己设计的数据增强.然后,介绍了分布式训练的数据加载方式,数据读取的整个 ...

  9. (蓝牙)网络编程中,使用InputStream read方法读取数据阻塞的解决方法

    问题如题,这个问题困扰了我好几天,今天终于解决了,感谢[1]. 首先,我要做的是android手机和电脑进行蓝牙通信,android发一句话,电脑端程序至少就要做到接受到那句话.android端发送信 ...

随机推荐

  1. python学习-47 random模块

    random模块 随机模块 random 的方法: print(random.random()) # [0,1] 的浮点数 print(random.randint(1,3)) print(rando ...

  2. Abp 领域事件简单实践 <二>

    上一篇说的是仓储增删改 的时候会自动触发领域事件. 其实也可以随时触发. 现在在应用层触发. 应用层依赖注入 EventBus public void Trigger() { var e = new ...

  3. 使用swagger在netcorewebapi项目中自动生成文档

    一.背景 随着前后端分离模式大行其道,我们需要将后端接口撰写成文档提供给前端,前端可以查看我们的接口,并测试,提高我们的开发效率,减少无效的沟通.在此情况下,通过代码自动生成文档,这种需求应运而生,s ...

  4. 通用http状态码

    400:Bad Request 表示客户端发出的请求不支持或无法识别,这通常是并未使用正确的请求语法.例如post或者put请求中资源的某个字段被设置为空的话,这将会导致一个Bad Request响应 ...

  5. Java 之 HashMap 集合

    一.HashMap 概述 java.util.HashMap<k,v> 集合 implements Map<k,v> 接口 HashMap 集合的特点: 1.HashMap 集 ...

  6. Go 方法使用

    方法的定义 在 Go 语言里,方法和函数只差了一个,那就是方法在 func 和标识符之间多了一个参数. type user struct { name string, email string, } ...

  7. oracle排序怎样弄成1 2 3 ,而不是 1 10 100

    oracle表字段设置得值不是number,而是Varchar2时排序就会出现这种问题 这个时候排序的时候需要转类型排序: order by to_number(顺序号) asc

  8. MySQL数字类型int与tinyint、float与decimal如何选择

    最近在准备给开发做一个mysql数据库开发规范方面培训,一步一步来,结合在生产环境发现的数据库方面的问题,从几个常用的数据类型说起. int.tinyint与bigint 它们都是(精确)整型数据类型 ...

  9. OGG 自动重启脚本

    6-20 * * * /oggdata/log/oggautorestart.sh >/oggdata/log/crontab_oggautorestart.log 2>&1 [说 ...

  10. Django drf:cbv(class base view)源码分析

    cbv是基于类的视图 # 首先要在路由层配置: # 找到类绑定方法as_view # 点开dispatch的方法 # http_method_names其实就是方法的列表 整个流程: 1.写一个基于类 ...