解決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");


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM