轉自:https://www.cnblogs.com/lylife/p/5519109.html
項目之前都是好好的,最近現場那邊出現一個問題,報錯不是合法的json字符串,這個json字符串是通過http請求訪問獲得的。
通過直接在瀏覽器上直接訪問http這個請求,發現返回的json也是完全正確的。后來排查代碼才發現了原來錯誤出在從字節流中讀取數據這里:
看下之前出錯代碼:這個方法是處理InputStream,然后返回成一個字符串。
1 public String process(InputStream in, String charset) { 2 byte[] buf = new byte[1024]; 3 StringBuffer sb = new StringBuffer(); 4 try { 5 while (in.read(buf) != -1) { 6 sb.append(new String(buf, charset)); 7 } 8 } catch (IOException e) { 9 e.printStackTrace(); 10 } 11 return sb.toString(); 12 }
有問題的代碼在第6行,發現之前項目沒出錯的原因是InputStream里面的數據少,還不夠1024個字節,while那里循環一次就好了,得到一個正確格式的json串;后面出錯了是因為InputStream里面數據比較多,while需要2次了,第一次讀取之后buf里面滿了,第二次讀取發現read(byte[])方法不會去清空緩沖區數組,第二次實際上read字節只有100個,buf里面只替換前100個字節內容,然后通過第6行代碼append到字符串里了,就造成了最后獲得的字符串不是json格式,造成之后json解析出錯。
知道問題后,將之前代碼改為下,既然每次不會去清空緩沖區數組內容,那就通過讀取長度來append字符串,問題解決:
1 public String process(InputStream in, String charset) { 2 byte[] buf = new byte[1024]; 3 StringBuffer sb = new StringBuffer(); 4 int len = 0; 5 try { 6 while ((len=in.read(buf)) != -1) { 7 sb.append(new String(buf, 0, len, charset)); 8 } 9 } catch (IOException e) { 10 e.printStackTrace(); 11 } 12 return sb.toString(); 13 }
后來查了下JDK API,發現API上也說明過了,只是以前沒注意,關鍵在於加黑字體,不影響b[k]到b[b.length-1]的元素:
附上API:
public int read(byte[] b) throws IOException
從輸入流中讀取一定數量的字節,並將其存儲在緩沖區數組b
中。以整數形式返回實際讀取的字節數。
在輸入數據可用、檢測到文件末尾或者拋出異常前,此方法一直阻塞。
如果b
的長度為 0,則不讀取任何字節並返回0
;否則,嘗試讀取至少一個字節。如果因為流位於文件末尾而沒有可用的字節,則返回值-1
;否則,至少讀取一個字節並將其存儲在b
中。將讀取的第一個字節存儲在元素b[0]
中,下一個存儲在b[1]
中,依次類推。讀取的字節數最多等於b
的長度。設 k 為實際讀取的字節數;這些字節將存儲在b[0]
到b[
k-1]
的元素中,不影響b[
k]
到b[b.length-1]
的元素。