通过http.client解析url返回的数据时为什么中文变成了unicode码

Posted 锋齐叶落

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过http.client解析url返回的数据时为什么中文变成了unicode码相关的知识,希望对你有一定的参考价值。

今天在解析json数据的时候得到了一堆这样的数据:{"errNum":0,"errMsg":"success","retData":[{"title":"\u6536\u5e9f\u54c1\u5927\u53d4\u521a\u4e0a\u53f0\uff0c\u5c31\u60e8\u906d\u8bc4\u59d4\u706d\u706f\uff0c\u4f46\u63a5\u4e0b\u6765\u5168\u573a\u90fd\u9707\u60ca\u4e86\uff01","url":"http:\/\/toutiao.com\/group\/6263036756505920002\/","abstract":"\u8ba2\u9605\u6211\u83b7\u53d6\u66f4\u591a\u7cbe\u5f69\u5185\u5bb9\uff01","image_url":"http:\/\/p1.pstatp.com\/list\/2f90009a31a7ee8bb15"}]}

这是因为,为了更好的传输中文,json进行了Unicode编码。

这样一来,我们在解析json之前,就得要先将json数据中的Unicode编码转换为我们使用的中文;

一:http请求数据返回json中string字段包含unicode的转码

 

  1. public static String decodeUnicode(String theString) {    
  2.         char aChar;    
  3.         int len = theString.length();    
  4.         StringBuffer outBuffer = new StringBuffer(len);    
  5.         for (int x = 0; x < len;) {    
  6.             aChar = theString.charAt(x++);    
  7.             if (aChar == ‘\\‘) {    
  8.                 aChar = theString.charAt(x++);    
  9.                 if (aChar == ‘u‘) {    
  10.                     // Read the xxxx    
  11.                     int value = 0;    
  12.                     for (int i = 0; i < 4; i++) {    
  13.                         aChar = theString.charAt(x++);    
  14.                         switch (aChar) {    
  15.                         case ‘0‘:    
  16.                         case ‘1‘:    
  17.                         case ‘2‘:    
  18.                         case ‘3‘:    
  19.                         case ‘4‘:    
  20.                         case ‘5‘:    
  21.                         case ‘6‘:    
  22.                         case ‘7‘:    
  23.                         case ‘8‘:    
  24.                         case ‘9‘:    
  25.                             value = (value << 4) + aChar - ‘0‘;    
  26.                             break;    
  27.                         case ‘a‘:    
  28.                         case ‘b‘:    
  29.                         case ‘c‘:    
  30.                         case ‘d‘:    
  31.                         case ‘e‘:    
  32.                         case ‘f‘:    
  33.                             value = (value << 4) + 10 + aChar - ‘a‘;    
  34.                             break;    
  35.                         case ‘A‘:    
  36.                         case ‘B‘:    
  37.                         case ‘C‘:    
  38.                         case ‘D‘:    
  39.                         case ‘E‘:    
  40.                         case ‘F‘:    
  41.                             value = (value << 4) + 10 + aChar - ‘A‘;    
  42.                             break;    
  43.                         default:    
  44.                             throw new IllegalArgumentException(    
  45.                                     "Malformed   \\uxxxx   encoding.");    
  46.                         }    
  47.         
  48.                     }    
  49.                     outBuffer.append((char) value);    
  50.                 } else {    
  51.                     if (aChar == ‘t‘)    
  52.                         aChar = ‘\t‘;    
  53.                     else if (aChar == ‘r‘)    
  54.                         aChar = ‘\r‘;    
  55.                     else if (aChar == ‘n‘)    
  56.                         aChar = ‘\n‘;    
  57.                     else if (aChar == ‘f‘)    
  58.                         aChar = ‘\f‘;    
  59.                     outBuffer.append(aChar);    
  60.                 }    
  61.             } else    
  62.                 outBuffer.append(aChar);    
  63.         }    
  64.         return outBuffer.toString();    
  65.     }  

二、普通string含有unicode转码方法

  1. public static String reEncoding(String text, String newEncoding) {   
  2.                String str = null;   
  3.                try {   
  4.                        str = new String(text.getBytes(), newEncoding);   
  5.                } catch (UnsupportedEncodingException e) {   
  6.                        log.error("不支持的字符编码" + newEncoding);   
  7.                        throw new RuntimeException(e);   
  8.                }   
  9.                return str;   
  10.        }   

三、说一下比较奇怪的方案,测试中无意发现的,暂时没弄明白原理(有明白原理的大神,请告知一声,谢谢)

我用HttpClent的post方式获取的json数据,得到的是带Unicode码的数据,需要转换成中文才行,但是转换的时间感觉有点长,就用HttpURLConnection的get方式又试了一下,在不转码的情况下,经过gson解析后,竟然神奇的自动转换成了中文:

技术分享

简直是太神奇了,而且需要的时间相对于HttpClient的post请求方式的请求和处理时间更短,所以,果断换用HttpURLConnection的get方式了

技术分享


①现在先贴一下HttpURLConnection的get的方式:

  1. @Test  
  2.     public void test() {  
  3.         try {  
  4.             long start = System.currentTimeMillis();  
  5.             URL url = new URL("http://apis.baidu.com/songshuxiansheng/news/news");  
  6.               
  7.             HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
  8.                 connection.addRequestProperty("apikey","0fc807e45a37ce264f45d169646f4a9e" );  
  9.                 String dataString = new String(GsonTools.IsToByte(connection.getInputStream()),"utf-8");  
  10.                 HeadlineJson newsJson = GsonTools.getObjectData(dataString, HeadlineJson.class);  
  11.                 List<Headline>list = newsJson.getRetData();  
  12.                 System.out.println(list.toString());  
  13.                 long end = System.currentTimeMillis();  
  14.                   
  15.             System.out.println("timeGap:"+(end-start));  
  16.         } catch (Exception e) {  
  17.             // TODO Auto-generated catch block  
  18.             e.printStackTrace();  
  19.         }  
  20.     }  


调用的GsonTools的方法:(之前的博文中有写到过)

  1. public static <T> T getObjectData(String jsonString, Class<T> type) {  
  2.   
  3.         T t = null;  
  4.         try {  
  5.             Gson gson = new Gson();  
  6.             t = gson.fromJson(jsonString, type);  
  7.         } catch (JsonSyntaxException e) {  
  8.             // TODO Auto-generated catch block  
  9.             e.printStackTrace();  
  10.         }  
  11.         return t;  
  12.     }  


②然后贴一下HttpClient的post方式:

  1. @Test  
  2.     public void TestHeadLine() {  
  3.         long start = System.currentTimeMillis();  
  4.         List<NameValuePair> params = new ArrayList<NameValuePair>();  
  5.         String url = "http://apis.baidu.com/songshuxiansheng/news/news";  
  6.         String jsonString = HttpUtils.getBaiDuString2(url, params);  
  7.         HeadlineJson lineJson = GsonTools.getObjectData(jsonString, HeadlineJson.class);  
  8.         System.out.println(lineJson.toString());  
  9.         long end = System.currentTimeMillis();  
  10.           
  11.         System.out.println("timeGap:"+(end-start));  
  12.     }  


调用的HttpUtils的方法:

  1. public static String getBaiDuString(String url,List<NameValuePair> params) {  
  2.         String serverDataString = null;  
  3.         HttpPost post = new HttpPost(url);  
  4.         try {  
  5.             post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));  
  6.             post.addHeader("apikey", UrlUtils.BAIDU_API_KEY);  
  7.             HttpClient client = new DefaultHttpClient();  
  8.             HttpResponse response = client.execute(post);  
  9.             int code = response.getStatusLine().getStatusCode();  
  10.             System.out.println("StatusCode:" + code);  
  11.   
  12.             if (code == 200) {  
  13.                 serverDataString = decodeUnicode(EntityUtils.toString(response.getEntity()));  
  14. //              serverDataString = EntityUtils.toString(response.getEntity());  
  15.   
  16.                 System.out.println("接收字符串数据成功\nServerData:"+serverDataString);  
  17.             }  
  18.         } catch (Exception e) {  
  19.             // TODO Auto-generated catch block  
  20.             e.printStackTrace();  
  21.         }  
  22.   
  23.         return serverDataString;  
  24.     }  


③调用的HttpClient的get方式

  1. public static String getBaiDuString2(String url,List<NameValuePair> params) {  
  2.         String serverDataString = null;  
  3.         HttpGet get = new HttpGet(url);  
  4.         try {get.addHeader("apikey", UrlUtils.BAIDU_API_KEY);  
  5.             HttpClient client = new DefaultHttpClient();  
  6.             HttpResponse response = client.execute(get);  
  7.             int code = response.getStatusLine().getStatusCode();  
  8.             System.out.println("StatusCode:" + code);  
  9.   
  10.             if (code == 200) {  
  11. //              serverDataString = decodeUnicode(EntityUtils.toString(response.getEntity()));  
  12.                 serverDataString = EntityUtils.toString(response.getEntity());  
  13.   
  14.                 System.out.println("接收字符串数据成功\nServerData:"+serverDataString);  
  15.             }  
  16.         } catch (Exception e) {  
  17.             // TODO Auto-generated catch block  
  18.             e.printStackTrace();  
  19.         }  
  20.   
  21.         return serverDataString;  
  22.     }  


谷歌提供的HttpClient的通信和HttpURLConnection网络通信的时间间隔我也做了比较,明显,HttpURLConnection的请求时间更短,所以果断使用HttpURLConnection的方式

四、java中本身就提供了对Unicode 的url进行解码的方法了:

 

    1. System.out.println(URLDecoder.decode("\u82f9\u679c", "utf-8")); 












以上是关于通过http.client解析url返回的数据时为什么中文变成了unicode码的主要内容,如果未能解决你的问题,请参考以下文章

Xslt在通过xsl文件解析时为负值添加括号'()'作为响应

注意:未定义的偏移量:返回千以下的数字时为1

使用Python爬取一个网页并解析

go语言中通过http访问需要认证的api

五种不同的 URL 参数解析方法的性能比较

golang入门案例之http client请求