Utf-8编码是如何工作的

关键字: 编码

Utf-8编码是如何工作的讲起。

(JVM规范第4.4.7提了一些,O'Reilly出的Java I/O里讲的比较详细,我手里的是第一版,在第14章,Mutillingual Character Sets and Unicode)

Java用的Unicode用两个字节表示一个charater,字母A用Hex表示是00 41, B是00 42,在一个纯英文的环境里面,直接存成Unicode的文件一半都是由零组成的,浪费资源。Utf-8的主要目的是对ASCII表格头128个字母优化,牺牲的是对中文字符的存储。

头128个字节(0到127),可以用七个bit来表示,x6 x5 x4 x3 x2 x1 x0.第八个bit永远是0

例子,A, 用Hex表示是00 41,去掉开头的零字节是Hex 41,转成二进制是 0100 0001。XP带的计算器可以在Hex和Binary
之间转换,自己试试。

第128到2047个字节,要用10个bit来表示

Java代码 复制代码
  1. 0  0  0  0  0 x10 x9 x8   
  2. 7 x6 x5 x4 x3 x2 x1 x0  
 0  0  0  0  0 x10 x9 x8
x7 x6 x5 x4 x3 x2 x1 x0


Utf-8就把这些字节编成下面这样的两个byte

Java代码 复制代码
  1. 1 1  0 x10 x9 x8 x7 x6   
  2. 1 0 x5 x4 x3 x2 x1 x0  
1 1  0 x10 x9 x8 x7 x6
1 0 x5 x4 x3 x2 x1 x0


第2048到65535个字节,要用16个bit来表示,Utf-8把这些字节编成下面这样的三个byte
Java代码 复制代码
  1. 1 1  1  0   x15 x14 x13 x12   
  2. 1 0 x11 x10 x9 x8 x7 x6   
  3. 1 0 x5 x4   x3 x2 x1 x0  
1 1  1  0   x15 x14 x13 x12
1 0 x11 x10 x9 x8 x7 x6
1 0 x5 x4   x3 x2 x1 x0


读一个Utf-8编码的array,如果第一个byte的高位是1110,那么要连读下面两个以 10 开头的byte。如果一个byte的高位是110,那么要连读下面一个以 10 开头的byte。
如果一个byte的高位是0,那么这个byte就是一个字符了。

可以做个练习,中文字"哈"的Unicode编码是Hex 54 C8,转成Utf-8是什么?

Hex 54 C8 转成十进制是21704,转成Utf-8后要用三个byte,找张纸,画三行,每行8个格子,第一行头四个格子填上1110,第二行头两个格子填上10,第三行头两个格子填上10。剩下的自己算算。然后和这个程序的结果比较一下。

Java代码 复制代码
  1. public class Test {   
  2.   public static void main(String[] args) {         
  3.     char c[] = { '\u54c8' };   
  4.     String ha = new String(c);   
  5.     byte b[] = null;   
  6.     try {   
  7.       b = ha.getBytes("utf-8");    
  8.     } catch (Exception e) { System.exit(-1);}   
  9.        
  10.     for(int i=0; i<b.length; i++) {   
  11.       System.out.print(Integer.toHexString(b[i]).substring(6) + " ");   
  12.     }   
  13.     System.out.println();   
  14.   }   
  15. }  
public class Test {
  public static void main(String[] args) {		
    char c[] = { '\u54c8' };
    String ha = new String(c);
    byte b[] = null;
    try {
      b = ha.getBytes("utf-8"); 
    } catch (Exception e) { System.exit(-1);}
	
    for(int i=0; i<b.length; i++) {
      System.out.print(Integer.toHexString(b[i]).substring(6) + " ");
    }
    System.out.println();
  }
}

转自: http://bigpanda.iteye.com/blog/31890
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值