zoukankan      html  css  js  c++  java
  • String.getBytes()方法中的中文编码问题

    String的getBytes()方法是得到一个系统默认的编码格式的字节数组
    getBytes("utf-8")  得到一个UTF-8格式的字节数组

    把String转换成bytes,各种编码转换成的bytes不同,比如UTF-8每个汉字转成3bytes,而GBK转成2bytes,所以要说明编码方式,否则用缺省编码。

    都是将一个string类型的字符串转换成byte类型并且存入一个byte数组中。
    在java中的所有数据底层都是字节,字节数据可以存入到byte数组。
    存储字符数据时(字符串就是字符数据),会先进行查表,然后将查询的结果写入设备,读取时也是先查表,把查到的内容打印到显示设备上
    getBytes()是使用默认的字符集进行转换,getBytes(“utf-8”)是使用UTF-8编码表进行转换。

    在Java中,String的getBytes()方法是得到一个操作系统默认的编码格式的字节数组。这表示在不同的操作系统下,返回的东西不一样!

    String.getBytes(String decode)方法会根据指定的decode编码返回某字符串在该编码下的byte数组表示,如:
    byte[] b_gbk = "中".getBytes("GBK");
    byte[] b_utf8 = "中".getBytes("UTF-8");
    byte[] b_iso88591 = "中".getBytes("ISO8859-1");
    将分别返回"中"这个汉字在GBK、UTF-8和ISO8859-1编码下的byte数组表示,此时

    b_gbk的长度为2,

    b_utf8的长度为3,

    b_iso88591的长度为1。

    而与getBytes相对的,可以通过new String(byte[], decode)的方式来还原这个"中"字,

    这个new String(byte[], decode)实际是使用指定的编码decode来将byte[]解析成字符串.
    String s_gbk = new String(b_gbk,"GBK");
    String s_utf8 = new String(b_utf8,"UTF-8");
    String s_iso88591 = new String(b_iso88591,"ISO8859-1");
    通过输出s_gbk、s_utf8和s_iso88591,会发现s_gbk和s_utf8都是"中",而只有s_iso88591是一个不被识别的字符(可以理解为乱码),为什么使用ISO8859-1编码再组合之后,无法还原"中"字?原因很简单,因为ISO8859-1编码的编码表根本就不包含汉字字符,当然也就无法通过"中".getBytes("ISO8859-1");来得到正确的"中"字在ISO8859-1中的编码值了,所以,再通过new String()来还原就更是无从谈起。
    因此,通过String.getBytes(String decode)方法来得到byte[]时,一定要确定decode的编码表中确实存在String表示的码值,这样得到的byte[]数组才能正确被还原。

    注意:

    有时候,为了让中文字符适应某些特殊要求(如http header要求其内容必须为iso8859-1编码),可能会通过将中文字符按照字节方式来编码的情况,如:
    String s_iso88591 = new String("中".getBytes("UTF-8"),"ISO8859-1"),这样得到的s_iso8859-1字符串实际是三个在ISO8859-1中的字符,在将这些字符传递到目的地后,目的地程序再通过相反的方式String s_utf8 = new String(s_iso88591.getBytes("ISO8859-1"),"UTF-8")来得到正确的中文汉字"中",这样就既保证了遵守协议规定、也支持中文。

     最近在学JSP,在学习处理get方式提交数据出现乱码问题的时候,对其中的一个解决方法new String(s.getBytes("iso-8859-1"),"utf-8");产生了疑问,就是为什么要使用s.getBytes("iso-8859-1")?

      当时只这样想的:客户端向服务器发送一个请求,比如说是一个字符串"请求";之后服务器接收到这个请求,也就是这个字符串,可是这时由于某种原因出现了乱码!这时为了解决这个问题,使用new String(s.getBytes("iso-8859-1"),"utf-8");解决问题。看到这条语句,我感觉想不通啊,字符使用iso-8859-1编码取得字节序列,再由utf-8解码取得字符串,得到的还是乱码啊!怎么会取得正确的字符呢!!!想不通啊!

      之后,通过查找资料,得到了一点想法,代码如下:

    复制代码
     1 public class ThinkIng {
     2     public static void main(String[] args) throws Exception {
     3         System.out.println("	------JSP模拟------");
     4         System.out.println("客户端,有一个中文字符的请求(转换成了字节序列发送),发送至服务器端");
     5         String request="请求";
     6         byte[] client=request.getBytes();//客户端的请求的字节序列
     7         print(client);
     8         System.out.println();//分割用的
     9         System.out.println("有一中间件,将发送的字符序列一默认的编码格式(iso-8859-1)进行解码");
    10         String sever=new String(client,"iso-8859-1");
    11         System.out.println(sever);
    12         System.out.println("程序猿发现,这边有问题,中文有乱码,前来解决!");
    13         String debug=new String(sever.getBytes("iso-8859-1"),"gbk");//还原字节序列,使用“gbk”重新进行解码!
    14         System.out.println(debug);
    15         System.out.println("问题解决!");
    16     }
    17     public static void print(byte[] b){//用于显示字节序列的
    18         for(byte b1:b){
    19             System.out.print(Integer.toHexString(b1 & 0xff)+" ");
    20         }
    21     }
    22 }
    复制代码

      先前没有想通主要是自己没注意到:

    1. 没有着重的想为什么会在输出时出现字符乱码?
    2. 客户端发送求时,字符转换成字节序列时的编码方式是什么样的?

      总的来说,乱码是由于编码方式与解码方式不一致导致的,这一句话没有理解透!如果当时这样想既然出现了乱码,肯定是那边的编码格式和解码格式不一致,就好了!

      注:编码:将字符串转换成字节序列;解码:将字节序列转换成字符串

      感谢:http://liguocai2009.iteye.com/blog/1602256这篇文章给我的启发!

    [java] view plain copy
     
    1. package com.test.bs;  
    2.   
    3. /** 
    4.  *  
    5.  * 1、Unicode是一种编码规范,是为解决全球字符通用编码而设计的,而rUTF-8,UTF-16等是这种规范的一种实现。 
    6.  
    7.    2、java内部采用Unicode编码规范,也就是支持多语言的,具体采用的UTF-16编码方式。 
    8.  
    9.    3、不管程序过程中用到了gbk,iso8859-1等格式,在存储与传递的过程中实际传递的都是Unicode编码的数据,要想接收到的值不出现乱码,就要保证传过去的时候用的是A编码,接收的时候也用A编码来转换接收。 
    10.  
    11.    4、如果双方的file.encoding确保都相同,那就省事了,都默认转了,但往往在不同项目交互时很多时候是不一致的,这个时候是必须要进行编码转换的。 
    12.  
    13.    5、无论如论转换,java程序的数据都是要先和Unicode做转换,这样也就是能处理多语言字符集的原因了。底层保持了一致,只要在传值和接值的时候也一致就肯定不会出现乱码了。 
    14.  * */  
    15. public class UnicodeTest1 {  
    16.   
    17.     public static void main(String args[]) throws Exception {  
    18.   
    19.         String str = "中文字符";  
    20.   
    21.         System.out.println("original string---" + str);// 会正常输出原始串  
    22.   
    23.         /** 
    24.          *  
    25.          * str.getBytes();  如果括号中不写charset,则采用的是Sytem.getProperty("file.encoding"),即当前文件的编码方式, 
    26.          *  
    27.          * 很多人写的是系统的默认编码,通过代码测试并非如此,实际得到的是文件的编码方式* 
    28.          *  
    29.          * str.getBytes("charset");//指定charset,即将底层存储的Unicode码解析为charset编码格式的字节数组方式 
    30.          *  
    31.          * String new_str=new String(str.getBytes("utf-8"),"gbk")); 
    32.          *  
    33.          * //将已经解析出来的字节数据转化为gbk编码格式的字符串,在内存中即为gbk格式的字节数组转为Unicode去交互传递 
    34.          */  
    35.   
    36.         String new_str = new String(str.getBytes("utf-8"), "gbk");  
    37.   
    38.         /** 
    39.          *  
    40.          * 此时的输出是乱码,在UTF-8的file.encoding下输出gbk格式的数据肯定是乱码,但是new_str的确是gbk编码式的 
    41.          *  
    42.          * 此时的乱码源于encoding不符,但gbk格式的new_str本身数据并没有问题,通过下面的转换也可以看得出来 
    43.          */  
    44.   
    45.         System.out.println("new string----" + new_str);  
    46.   
    47.         String final_str = new String(new_str.getBytes("gbk"), "utf-8");// 此处的含意与最上边的注释是一致的参数含意  
    48.   
    49.         /** 
    50.          *  
    51.          *输出是正常的,此时将gbk编码格式的new_str字符串,用gbk这个charset去解析它,然后用utf-8再转码一次, 
    52.          *  
    53.          * 因为new_str确实是gbk格式的,才能经过utf-8编码得到正常的数据显示。 
    54.          */  
    55.   
    56.         System.out.println("final string---" + final_str);  
    57.   
    58.     }  
    59.   
    60. }  


     

    [java] view plain copy
     
      1. package com.test.bs;  
      2.   
      3. import java.io.UnsupportedEncodingException;  
      4.   
      5. public class UnicodeTest2 {  
      6.   
      7.     public static void main(String[] args) {  
      8.         String a = "哈哈";  
      9.         try {  
      10.             byte[] gb2312 = a.getBytes("GB2312");  
      11.             byte[] utf = a.getBytes("UTF-8");  
      12.             for (int i = 0; i < gb2312.length; i++) {  
      13.                 System.out.print(gb2312[i]);  
      14.             }  
      15.             System.out.println();  
      16.   
      17.             for (int i = 0; i < utf.length; i++) {  
      18.                 System.out.print(utf[i]);  
      19.             }  
      20.             System.out.println();  
      21.   
      22.             System.out.println(new String(gb2312));  
      23.             System.out.println(new String(utf));  
      24.             System.out.println(System.getProperty("file.encoding"));//当前文件的编码方式  
      25.             System.out.println(new String(utf, "UTF-8"));  
      26.             System.out.println(new String(gb2312, "UTF-8"));  
      27.         } catch (UnsupportedEncodingException e) {  
      28.             e.printStackTrace();  
      29.         }  
      30.   
      31.     }  
      32. }  
  • 相关阅读:
    Linux学习笔记(二)
    Linux学习笔记(三)
    C++学习笔记一
    汇编总结
    Linux学习笔记(一)
    编辑距离算法
    Linux学习笔记(四)
    Linux学习笔记五
    extjs model的dirty属性能够查询store中某一个行是否改变过
    Ext.grid.Panel一定要有renderTo或autoRender属性,不然页面为空
  • 原文地址:https://www.cnblogs.com/wwwcnblogscom/p/8318022.html
Copyright © 2011-2022 走看看