ゞ沉默是金ゞ

鱼离不开水,但是没有说不离开哪滴水.
posts - 98,comments - 104,trackbacks - 0
         今天把JAVA里一个比较头痛的问题“字符编码”研究了一下,分享一下。

  众所周知,JAVA为了国际通用,用的是UNICODE来保存里面的字符。而UNICODE只是一个种字符集,字符的存储和表示要用到一定的字符编码格式,而与UNICODE对应的字符编码格式就是我们常看到的UTF-8,UTF-16等等,而UTF-8是最常用的,所以人们常常把它和UNICODE等同起来,这在某些情况下是没有错的,但这样的理解在JAVA里就会产生一些混淆。我们用下面的程序来演示一下。

  定义一个字符串

  String name = "堂";

  这个字符串就一个字符,把它取出来

  char c_name = name.charAt(0);

  JAVA里的char型是十六位的(两个字节),但是如果是用UTF-8的话可能会不只两位(UTF-8是变长存储的),那看来JAVA本身并不是用UTF-8来保存的,口说无凭,做个实验吧。

  首先看看char里保存的内容  
int low = (c_name) & 0xff;//取c_name的低位
int high = (c_name >> 8) & 0xff;//取c_name的高位
System.out.println(Integer.toHexString(high) + " " + Integer.toHexString(low));
  结果是58 02

  只有两个字节而已(16位),那么真正的UTF-8编码的内容是什么呢,再看看吧。

  为了方便,我写了一个辅助方法printbyte,作用是把一个byte数组的每个元素按照十六进制格式打印出来,同样为了方便,我把它作为静态方法。 

 public static void printbyte(byte[] bt)
 {
      for (int i = 0; i < bt.length; i++)
      {
              int hex = (int)bt[i] & 0xff;
              System.out.print(Integer.toHexString(hex) + " ");
      }
      System.out.println(" length = "+bt.length);
 }


 byte[] utf_8 = name.getBytes("utf-8");
 printbyte(utf_8);

  结果是e5 a0 82 length = 3

  哇,三个字节!看来JAVA内部用的真不是UTF-8,那用的是什么呢?UTF-16?看一下便知。  
byte[] utf_16 = name.getBytes("utf-16");
printbyte(utf_16);
  结果是fe ff 58 02 length = 4,靠,四个字节了。咦?后面的低16位不正是和开始c_name的十六进制表示一样的吗?看来JAVA真正的内部字符编码和UTF-16有或多或少的联系。JAVA内部究竟是用的什么字符编码呢?这个问题我也找了很久,后来在THINK IN JAVA 3rd的12章里看到一个例子出现了UTF-16BE,难道是它?  
byte[] utf_16be = name.getBytes("utf-16be");
printbyte(utf_16be);
结果出来了:58 02 length = 2
  哈哈,I got it!不多不少两个字节,内容也一样。果然是它。同时我在里面也看到,UNICODE的编码还有一个LE,这里的BE,LE我想应该是bigendian和littleendian吧。

    附上全代码:
    

public class CodeTest {
    
public static void printbyte(byte[] bt) {
        
for (int i = 0; i < bt.length; i++{
            
int hex = (int) bt[i] & 0xff;
            System.out.print(Integer.toHexString(hex) 
+ " ");
        }

        System.out.println(
" length = " + bt.length);
    }


    
public static void main(String[] args) throws Exception {
        String name 
= "";
        
char c_name = name.charAt(0);
        
        System.out.println(c_name);
// JAVA里的char型是十六位的(两个字节)
        
        
int low = (c_name) & 0xff;// 取c_name的低位
        int high = (c_name >> 8& 0xff;// 取c_name的高位
        System.out.println(Integer.toHexString(high) + " "
                
+ Integer.toHexString(low));  //58 2
        
        
byte[] utf_8 = name.getBytes("utf-8");
        printbyte(utf_8);  
//e5 a0 82  length = 3
        
        
byte[] utf_16 = name.getBytes("utf-16"); 
        printbyte(utf_16);  
//fe ff 58 2  length = 4
        
        
byte[] utf_16be = name.getBytes("utf-16be"); 
        printbyte(utf_16be); 
//58 2  length = 2
        
        
byte[] utf_16le = name.getBytes("utf-16le");
        printbyte(utf_16le); 
// 2 58  length = 2
    }

}
posted on 2008-12-30 14:53 ゞ沉默是金ゞ 阅读(221) 评论(0)  编辑  收藏 所属分类: Java SE

只有注册用户登录后才能发表评论。


网站导航: