http://www.cn-java.com/www1/?uid-560221-action-viewspace-itemid-8390

 

一、Java编码是怎么回事?

对于使用中文以及其他非拉丁语系语言的开发人员来说,经常会遇到字符集编码问题。对于Java语言来说,在其内部使用的是UCS2编码(2个字节的Unicode编码)。这种编码并不属于某个语系的语言编码,它实际上是一种编码格式的世界语。在这个世界上所有可以在计算机中使用的语言都有对应的UCS2编码。

正是因为Java采用了UCS2,因此,在Java中可以使用世界上任何国家的语言来为变量名、方法名、类起名,如下面代码如下:

class 中国 {     public String 雄起()     {          return "中国雄起";     } }  中国 祖国 = new 中国(); System.out.println(祖国.雄起()); 
 class 中国  
 {  
     
public String 雄起()  
     {  
          
return "中国雄起";  
     }  
 }  
   
 中国 祖国 
= new 中国();  
 System.out.println(祖国.雄起());  


 

 哈哈,是不是有点象“中文编程”。实际上,也可以使用其他的语言来编程,如下面用韩文和日文来定义个类:


class 수퍼맨 {     public void スーパーマン() {  } }
 class 수퍼맨  
 {  
     
public void スーパーマン() {  }  
  }  


 

  实际上,由于Java内部使用的是UCS2编码格式,因为,Java并不关心所使用的是哪种语言,而只要这种语言在UCS2中有定义就可以。

    UCS2编码中为不同国家的语言进行了分页,这个分页也叫“代码页”或“编码页”。中文根据包含中文字符的多少,分了很多代码页,如cp935cp936等,然而,这些都是在UCS2中的代码页名,而对于操作系统来说,如微软的windows,一开始的中文编码为GB2312,后来扩展成了GBK。其实GBKcp936是完全等效的,用它们哪个都行。

二、Java编码转换

    上面说了这么多,在这一部分我们做一些编码转换,看看会发生什么事情。

    先定义一个字符串变量:

    String gbk = "中国"; // “中国”在Java内部是以UCS2格式保存的

    用下面的语言输出一定会输出中文:

System.out.println(gbk);

    实现上,当我们从IDE输入“中国”时,用的是java源代码文件保存的格式,一般是GBK,有时也可是utf-8,而在Java编译程序时,会不由分说地将所有的编码格式转换成utf-8编码,读者可以用UltraEdit或其他的二进制编辑器打开上面的“中国.class”,看看所生成的二进制是否有utf-8的编码(utf-8ucs2之间的转换非常容易,因为utf-8ucs2之间是用公式进行转换的,而不是到代码页去查,这就相当于将二进制转成16进制一样,4个字节一组)。如“中国”的utf-8编码按着GBK解析就是“涓  浗”。如下图所示。


【转】Java编码原理与解决方案

如果使用下面的语言可以获得“中国”的utf-8字节,结果是6(一个汉字由3个字节组成)

System.out.println(gbk.getBytes("utf-8").length);

下面的代码将输出“涓  浗”。

System.out.println(new String(gbk.getBytes("utf-8"), "gbk"));   

由于将“中国“的utf-8编码格式按着gbk解析,所以会出现乱码。

如果要返回中文的UCS2编码,可以使用下面的代码:

System.out.println(gbk.getBytes("unicode")[2]);

System.out.println(gbk.getBytes("unicode")[3]);

前两个字节是标识位,要从第3个字节开始。还有就是其他的语言使用的编码的字节顺序可能不同,如在C#中可以使用下面的代码获得“中国“的UCS2编码:

String s = "";

MessageBox.Show(ASCIIEncoding.Unicode.GetBytes(s)[0].ToString());

MessageBox.Show(ASCIIEncoding.Unicode.GetBytes(s)[1].ToString());

    使用上面的java代码获得的“中“的16进制UCS2编码为4E2D,而使用C#获得的相应的ucs2编码为2D4E,这只是C#Java编码内部使用的问题,并没有什么关系。但在C#Java互操作时要注意这一点。

    如果使用下面的java编码将获得16进制的“中”的GBK编码:

System.out.println(Integer.toHexString(0xff & xyz.getBytes("gbk")[0]));

System.out.println(Integer.toHexString(0xff & xyz.getBytes("gbk")[1]));

“中”的ucs2编码为2D4EGBK编码为D6D0

    读者可访问如下的url自行查验:

    http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT

    当然,感兴趣的读者也可以试试其他语言的编码,如“人类”的韩语是“인간의”,如下面的代码将输出“인간의”的cp949ucs2编码,其中cp949是韩语的代码页。

String korean = "인간의"// 共三个韩文字符,我们只测试第一个“인”   
System.out.println(Integer.toHexString(0xff & korean.getBytes("unicode")[2]));  
System.out.println(Integer.toHexString(
0xff & korean.getBytes("unicode")[3]));  
System.out.println(Integer.toHexString(
0xff & korean.getBytes("Cp949")[0]));  
System.out.println(Integer.toHexString(
0xff & korean.getBytes("Cp949")[1])); 


相关文章:

  • 2022-12-23
  • 2021-04-16
  • 2021-11-27
  • 2022-12-23
  • 2021-12-19
  • 2022-12-23
  • 2021-08-24
  • 2021-12-12
猜你喜欢
  • 2022-12-23
  • 2021-06-04
  • 2022-02-18
  • 2022-12-23
  • 2022-01-09
  • 2021-09-27
相关资源
相似解决方案