为什么一个汉字查出来的Unicode是2个字节(16位),但UTF-8转出来却是3个字节(24位)?

Java 1820℃

今天在使用java的String类的byte[] getBytes()方法,发现汉字转出来的数组是三个字节,都知道UTF-8的中文字符占三个字节,这个没有问题,可是使用Unicode编码转换查出来的汉字只有两个字节,这底层又是如何对应存储的呢?我仔细研究了下,专门记录于此,以备后用:

首先计算机底层是使用二进制存储的,一个二进制叫做位或比特(bit),8位(bit)叫一个字节(byte),一个字符占多少字节取决于编码方式,例如查到”李”对应的Unicode十六进制编码是:\u674e。通过计算器换算成二进制:

0110  0111  0100  1110

至此,可以得出的结论是汉字使用Unicode字符集存储应该占两个字节(16位)。

接下来,使用java将其转换成字节数组形式:

byte[] bytes = "李".getBytes("utf-8");
for (byte b : bytes) {
    System.out.println(b);
}
输出:
-26
-99
-114

通过计算器将-26、-99、-114这个三个数字转成二进制:

1110  0110  1001  1101  1000  1110

猛一看,发现这串二进制数字和上面的Unicode对应的二进制数字没有任何相似之处啊,明明网上说法是“UTF-8是Unicode的一种实现方式”,但是这明显没有半毛钱关系啊,我靠,难道网上这些人在胡说,还是我的打开方式不对??

心想,你两不是没关系吗?那我就把你们硬两放在一起,让你们发生点关系。。。

11100110    10011101    10001110
    0110      011101      001110

这么一分割,貌似还真有点关系了,上网找到如下资料:

Unicode符号范围           |  UTF-8编码方式
(十六进制)                      | (二进制)
—————————————————————–————————————–
0000 0000-0000 007F   | 0xxxxxxx                 #UTF-8规定此范围字符占1字节,首位定死为0。
0000 0080-0000 07FF   | 110xxxxx 10xxxxxx  #UTF-8规定占2字节,高位字节前3位为110,低位前2位为10。
0000 0800-0000 FFFF   | 1110xxxx 10xxxxxx 10xxxxxx  #占3字节,高位字节前3位为1110,后面低位前2位一律为10。
0001 0000-0010 FFFF   | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx #占4字节,高位字节前3位为11110,后面前2位一律为10。

这下再想想“utf-8是一种变长字节编码方式”这句话,说的是这个意思啊。

转载请注明:零五宝典 » 为什么一个汉字查出来的Unicode是2个字节(16位),但UTF-8转出来却是3个字节(24位)?