2015-04-05 82 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);