【问题标题】:Android ByteArrayOutputStream corrupting HTTP GET JSONArrayAndroid ByteArrayOutputStream 破坏 HTTP GET JSONArray
【发布时间】:2015-04-05 02:00:39
【问题描述】:

我正在使用此代码解析从服务器获取的 JSON 数组。

    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;

此代码在我的手机上运行良好。不幸的是,当我在 Google Nexus 7 的虚拟设备上使用 Genymotion 模拟器时,JSON 数组略有改变。 95% 的 JSON 数组很好,但它在接近尾声时被截断,并且在字符 1253 处随机丢失了 json 数组的大约 4 个字符,所以我得到:

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

我认为这是模拟器的一些内存问题。它的基本内存是 1024。虽然增加这个数量并不会改变任何东西。 任何有关问题背后原因的提示将不胜感激。另外,如果您发现有改进的余地,请随时评论我的代码。 :)

【问题讨论】:

    标签: android json genymotion bytearrayoutputstream


    【解决方案1】:

    这很奇怪。

    我可以想到两件事来尝试:

    • 检查服务器的编码和String构造函数的编码。

    服务器可能正在使用 Latin-1 (ISO-8859-1) 进行解码,而字符串正在使用 UTF-8 进行编码。但是 JSON 应该以 Unicode 格式发送,Android 的默认字符集是 UTF-8。检查 HTTP Content-type 响应头;它应该说:application/json; charset=utf-8。如果charset 部分不存在,请进行一些调查并找出您的服务器用于解码 HTTP 流的字符集。并检查手机和模拟器上的默认字符集是否相同;它应该是 UTF-8。

    • 在读取数据之后、构造字符串之前尝试在 ByteArrayOutputStream 上调用 flush()。

    手机操作系统和模拟器操作系统在传输/缓冲/刷新流数据的方式上可能存在细微差别。

    如果flush() 不起作用,请尝试在不使用 ByteArrayOutputStream 的情况下重写代码。例如,您可以使用InputStreamReader 包装输入流,它读取字符而不是字节,然后使用StringBuilder 或StringBuffer 附加字符。

    使代码更好的一种方法是使用JSONReader 而不是JSONArray 或JSONObject。 JSONReader 将包装一个 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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-05-09
        • 2017-10-13
        • 1970-01-01
        • 1970-01-01
        • 2022-08-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多