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


    今天在解析json数据的时候得到了一堆这样的数据:{"errNum":0,"errMsg":"success","retData":[{"title":"u6536u5e9fu54c1u5927u53d4u521au4e0au53f0uff0cu5c31u60e8u906du8bc4u59d4u706du706fuff0cu4f46u63a5u4e0bu6765u5168u573au90fdu9707u60cau4e86uff01","url":"http://toutiao.com/group/6263036756505920002/","abstract":"u8ba2u9605u6211u83b7u53d6u66f4u591au7cbeu5f69u5185u5bb9uff01","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 = ' ';    
    53.                     else if (aChar == 'r')    
    54.                         aChar = ' ';    
    55.                     else if (aChar == 'n')    
    56.                         aChar = ' ';    
    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("接收字符串数据成功 ServerData:"+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("接收字符串数据成功 ServerData:"+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("u82f9u679c", "utf-8"));  详细介绍请查看全文:https://cnblogs.com/qianzf/
  • 相关阅读:
    java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener问题解决
    开发人员系统功能设计常用办公软件分享
    微信自定义菜单url默认80端口问题解决
    Servlet再度学习
    JSP九大内置对象
    linux下安装apache(httpd-2.4.3版本)各种坑
    Ajax原理学习
    Shell脚本了解
    生成Webservice的两种方式(Axis2,CXf2.x)
    Webservice发布
  • 原文地址:https://www.cnblogs.com/qianzf/p/7750761.html
Copyright © 2020-2023  润新知