2015-04-05 53 views
2

我正在使用此代碼來解析從我的服務器獲得的JSON數組。Android ByteArrayOutputStream損壞HTTP GET JSONArray

try { 
      URL u = new URL("http://54.68.139.250/get_user_likes"); 
      HttpURLConnection conn = (HttpURLConnection) u.openConnection(); 
      conn.setRequestMethod("GET"); 

      conn.connect(); 
      InputStream is = conn.getInputStream(); 
      byte[] b = new byte[1024]; 
      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 

      while (is.read(b) != -1) 
       baos.write(b); 

      String JSONResp = new String(baos.toByteArray()); 

      JSONArray arr = new JSONArray(JSONResp); 
      for (int i=0; i < arr.length(); i++) { 
       result.add(convertArticle(arr.getJSONObject(i))); 
      } 
      return result; 
     } 
     catch(Throwable t) { 
      t.printStackTrace(); 
     } 
     return null; 

此代碼在我的手機上效果很好。不幸的是,當我在谷歌Nexus 7的虛擬設備上使用Genymotion仿真器時,JSON數組稍有改動。 JSON數組的95%是好的,但它被截斷接近盡頭,在字符1253是隨機丟失約4 JSON數組的字符,所以我越來越:

org.json.JSONException: Expected ':' after top_id at character 1253 of [{"top_id":6,"top_url": 

我想這是模擬器存在一些內存問題。它的基本內存是1024.增加這個數量雖然不會改變任何東西。 任何有關問題背後的原因,將不勝感激。此外,如果您看到有待改進的餘地,請隨時對我的代碼發表評論。 :)

回答

2

這很奇怪。

我能想到的兩件事情嘗試:

  • 檢查服務器的編碼和String構造的編碼。

服務器可能使用Latin-1(ISO-8859-1)進行解碼,而String使用UTF-8進行編碼。但是JSON應該是用Unicode發送的,Android的默認字符集是UTF-8。檢查HTTP Content-type響應頭;應該說:application/json; charset=utf-8。如果charset部分不存在,請進行一些調查並找出服務器用於解碼HTTP流的字符集。並檢查手機和模擬器上的默認字符集是否相同;它應該是UTF-8。

  • 嘗試在讀取數據之後以及構造字符串之前,在ByteArrayOutputStream上調用flush()

這可能是電話操作系統和仿真器操作系統之間在流數據傳輸/緩衝/刷新方式上存在細微的差異。

如果flush()不起作用,請嘗試在不使用ByteArrayOutputStream的情況下重寫代碼。例如,您可以使用InputStreamReader來包裝輸入流,該文件讀取字符而不是字節,然後使用StringBuilderStringBuffer附加字符。

您可以使代碼更好的一種方法是使用JSONReader而不是JSONArrayJSONObjectJSONReader將包裝一個InputStreamReader,它反過來包裝HTTP輸入流。它可以更快,更高效地存儲內存,因爲在開始解析數據之前不必讀取整個輸入流。當服務器發送大量的JSON數據時,這可能會產生很大的不同。

2

您應該檢查返回值is.read()。更改

 while (is.read(b) != -1) 
      baos.write(b); 

 int nread; 
    while ((nread=is.read(b)) != -1) 
      baos.write(b, 0, nread);