【问题标题】:Converting String to Android JSONObject loses utf-8将 String 转换为 Android JSONObject 会丢失 utf-8
【发布时间】:2016-04-13 18:01:24
【问题描述】:

我正在尝试从 URL 获取(JSON 格式)字符串并将其作为 Json 对象使用。当我将字符串转换为 JSONObject 时,我丢失了 UTF-8 编码。

这是我用来连接url并获取字符串的函数:

private static String getUrlContents(String theUrl) {
    StringBuilder content = new StringBuilder();
    try {
        URL url = new URL(theUrl);
        URLConnection urlConnection = url.openConnection();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));

        String line;
        while ((line = bufferedReader.readLine()) != null) {
            content.append(line + "\n");
        }
        bufferedReader.close();
    } catch(Exception e) {
        e.printStackTrace();
    }

    return content.toString();
}

当我从服务器获取数据时,以下代码显示正确的字符:

String output = getUrlContents(url);
Log.i("message1", output);

但是当我将输出字符串转换为 JSONObject 时,波斯字符变成了这样的问号??????。 (messages 是 JSON 中的数组名)

JSONObject reader = new JSONObject(output);
String messages = new String(reader.getString("messages").getBytes("ISO-8859-1"), "UTF-8");
Log.i("message2", messages);

【问题讨论】:

    标签: android json utf-8 jsonobject


    【解决方案1】:

    您是在告诉 Java 使用 ISO-8859-1 将字符串(带有键 message)转换为字节,而不是从这些字节创建一个新的字符串,解释为 UTF-8。

    new String(reader.getString("messages").getBytes("ISO-8859-1"), "UTF-8");
    

    你可以简单地使用:

    String messages = reader.getString("messages");
    

    【讨论】:

    • 之所以有效,是因为您通过网络接收的字节已经在 getUrlContents 中正确解释,并且在内部存储为 UTF-16 字符串。
    • getUrlContents 仅在服务器的字符编码与客户端的字符编码匹配时有效。
    【解决方案2】:

    您可以按如下方式更新您的代码:

        private static String getUrlContents(String theUrl) {
            StringBuilder content = new StringBuilder();
            try {
                URL url = new URL(theUrl);
                URLConnection urlConnection = url.openConnection();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8"));
    
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    content.append(line).append("\n");
                }
                bufferedReader.close();
            } catch(Exception e) {
                e.printStackTrace();
            }
    
            return content.toString().trim();
        }
    

    【讨论】:

      【解决方案3】:

      您有两个编码问题:

      1. 服务器发送以字符集编码的文本。设置 InputStreamReader 时,需要传递服务器使用的编码,以便正确解码。字符编码通常在Content-type HTTP 响应中的charset 字段中给出。 JSON 通常是 UTF-8 编码的,但也可以是合法的 UTF-16 和 UTF-32,因此您需要检查。如果没有指定的编码,将字节编组为字符串时将使用您的系统环境,反之亦然。基本上,您应该始终指定字符集。

      2. String messages = new String(reader.getString("messages").getBytes("ISO-8859-1"), "UTF-8"); 显然会导致问题(如果您有非 ascii 字符) - 它将字符串编码为 ISO-8995-1,然后尝试将其解码为 UTF-8。

      在读取输入流之前,可以使用简单的正则表达式模式从 Content-type 标头中提取 charset 值。我还包含了一个简洁的 InputStream -> 字符串转换器。

      private static String getUrlContents(String theUrl) {
      
          try {
              URL url = new URL(theUrl);
              URLConnection urlConnection = url.openConnection();
              InputStream is = urlConnection.getInputStream();
      
              // Get charset field from Content-Type header
              String contentType = urlConnection.getContentType();
              // matches value in key / value pair
              Pattern encodingPattern = Pattern.compile(".*charset\\s*=\\s*([\\w-]+).*");
              Matcher encodingMatcher = encodingPattern.matcher(contentType);
              // set charsetString to match value if charset is given, else default to UTF-8
              String charsetString = encodingMatcher.matches() ? encodingMatcher.group(1) : "UTF-8";
      
              // Quick way to read from InputStream.
              // \A is a boundary match for beginning of the input
              return new Scanner(is, charsetString).useDelimiter("\\A").next();
          } catch(Exception e) {
              e.printStackTrace();
          }
      
          return null;
      }
      

      【讨论】:

        【解决方案4】:

        不确定这是否会有所帮助,但您也许可以这样做:

        JSONObject result = null;
        String str = null;
        try 
        {           
            str = new String(output, "UTF-8");
            result = (JSONObject) new JSONTokener(str).nextValue();
        } 
        catch (Exception e) {}
        
        String messages = result.getString("messages");
        

        【讨论】:

          猜你喜欢
          • 2011-01-07
          • 2014-03-01
          • 2017-09-24
          • 2013-04-25
          • 2014-09-19
          • 2019-02-03
          • 1970-01-01
          • 2011-11-01
          • 2013-09-26
          相关资源
          最近更新 更多