zoukankan      html  css  js  c++  java
  • 解决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");
  • 相关阅读:
    官网英文版学习——RabbitMQ学习笔记(四)Work queues
    官网英文版学习——RabbitMQ学习笔记(三)Hello World!
    官网英文版学习——RabbitMQ学习笔记(二)RabbitMQ安装
    微服务中springboot启动问题
    nodejs-mime类型
    nodejs-mime类型
    const isProduction = process.env.NODE_ENV === 'production'; 作用
    单向绑定
    建立Model
    使用Sequelize
  • 原文地址:https://www.cnblogs.com/renjiaqi/p/11411915.html
Copyright © 2011-2022 走看看