今天在使用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位)?