解决InputStream中数据读取不完整问题
转载: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中数据读取不完整问题的更多相关文章
- 如何解决wamp中数据库读取数据是???的情况?
数据库中数据正常,但是从数据库读取出的数据在网页中显示时是???,该怎么办呢? 左键点击托盘区的WampServer图标,选择Mysql--my.ini,就会打开配置文件 1.在[client]段落增 ...
- 3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案
根据之前解析的循环依赖的源码, 分析了一级缓存,二级缓存,三级缓存的作用以及如何解决循环依赖的. 然而在多线程的情况下, Spring在创建bean的过程中, 可能会读取到不完整的bean. 下面, ...
- BlockingQueue阻塞队列(解决多线程中数据安全问题 可用于抢票,秒杀)
案例:一个线程类中 private static BlockingQueue<Map<String, String>> dataQueue = new LinkedBlocki ...
- TensorFlow中数据读取之tfrecords
关于Tensorflow读取数据,官网给出了三种方法: 供给数据(Feeding): 在TensorFlow程序运行的每一步, 让Python代码来供给数据. 从文件读取数据: 在TensorFlow ...
- 解决Redis中数据不一致问题
redis系列之数据库与缓存数据一致性解决方案 数据库与缓存读写模式策略写完数据库后是否需要马上更新缓存还是直接删除缓存? (1).如果写数据库的值与更新到缓存值是一样的,不需要经过任何的计算,可以马 ...
- TensorFlow中数据读取—如何载入样本
考虑到要是自己去做一个项目,那么第一步是如何把数据导入到代码中,何种形式呢?是否需要做预处理?官网中给的实例mnist,数据导入都是写好的模块,那么自己的数据呢? 一.从文件中读取数据(CSV文件.二 ...
- Spark(十二)【SparkSql中数据读取和保存】
一. 读取和保存说明 SparkSQL提供了通用的保存数据和数据加载的方式,还提供了专用的方式 读取:通用和专用 保存 保存有四种模式: 默认: error : 输出目录存在就报错 append: 向 ...
- 从零搭建Pytorch模型教程(一)数据读取
前言 本文介绍了classdataset的几个要点,由哪些部分组成,每个部分需要完成哪些事情,如何进行数据增强,如何实现自己设计的数据增强.然后,介绍了分布式训练的数据加载方式,数据读取的整个 ...
- (蓝牙)网络编程中,使用InputStream read方法读取数据阻塞的解决方法
问题如题,这个问题困扰了我好几天,今天终于解决了,感谢[1]. 首先,我要做的是android手机和电脑进行蓝牙通信,android发一句话,电脑端程序至少就要做到接受到那句话.android端发送信 ...
随机推荐
- Nginx学习笔记(三):Nginx 请求处理
Request Nginx 中的 ngx_http_request_t 是对一个 http 请求的封装: 一个 http 请求包含:请求行.请求头.请求体,响应行.响应头.响应体 Nginx 处理请求 ...
- 使用DANT做FTP的转发代理
FTP不能直接使用nginx进行转发,想了一些办法,最后决定使用iptalbes做DNAT,相关于把这个机器做一台防火墙,做一个NAT 1.启用ip_forward vim /etc/sysctl.c ...
- php底层源码之数组
数组key和value的限制条件 <?php $arr = array( 1 => 'a', "1" => "b", 1.5 => &q ...
- C语言数组不知道输入几个整数以及输入一直到为0
输入一直到为0: ){ } 数组不知道输入几个整数: ],num=; for(;;num++){ scanf("%d",&array[num]); if(getchar() ...
- DotNet跨平台 - docker部署.net core2.0项目
参考文档: https://docs.docker.com/install/linux/docker-ce/centos/ http://www.dockerinfo.net/document htt ...
- openmp 和 thread 性能实测
#include <stdio.h> #include <iostream> #include <thread> #include<omp.h> //# ...
- VBA决策(十)
决策允许程序员控制脚本或其中一个部分的执行流程.执行由一个或多个条件语句控制.以下是在大多数编程语言中找到的典型决策结构的一般形式. VBA提供了以下类型的决策声明. 点击以下链接来查看它们的详细信息 ...
- css的导入与基础选择器
css是什么 css也是一门标记语言,主要用作修改控制html的样式 css书写的位置(导入) css是用来控制页面标签的样式,但是可以根据实际情况书写在不同的位置, 放在不同位置有不同的专业叫法,可 ...
- 如何判断是否是ssd硬盘?win10查看固态硬盘的方法
转自:http://www.w10zj.com/Win10xy/Win10yh_7732.html 如何判断是否是ssd硬盘?在win10操作系统中我们该如何查看当前主机中安装的是固态硬盘还是机械硬盘 ...
- python matplotlib拟合直线
import numpy as np import matplotlib.pyplot as plt plt.rcParams['font.family'] = ['sans-serif'] plt. ...