Unicode、UTF-8和UTF-16
??先说一下字符集,顾名思义,就是各种文字和符号的集合。常见的字符集包括Unicode、ASCII,GBK等。小可爱们,开门即遇坑,在这里一定要注意,UTF-8和UTF-16不是字符集哦!那它俩是啥,又和Unicode有什么区别呢?请继续看下去。
??众所周知,Unicode被称为万国码,是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。所以说每一个字符在Unicode中都有唯一的编码。这些编码值就被称为码点。同时,Unicode标准中还指出码点由十六进制书写。在ASCII中,一个ASCII码占用8个二进制位,即一个字节。那么一个Unicode码点占几个字节呢?嘿嘿嘿,其实这样问本身是有问题的。Unicode只规定了字符的二进制表示方式,并没有指出这些二进制数据如何在计算机中存储。为什么呢,我们都知道ASCII字符集中’A’是0100 0001、’a’是0110 0001,即一个ASCII占据1个字节。但在Unicode中则不同了,举个例子。’严’这个字符在Unicode中的码点是4E25,转换成二进制数是100 1110 0010 0101,’A’的码点为0041,转化为二进制数是0100 0001。它俩的长度竟然相差这么大!也就是说如果按2字节存储,A的二进制数会有9位无效的0,但要是按照长度选取最小的字节长度来存储,计算机又怎么知道什么时候该读1字节,什么时候该读2字节呢?这时候UTF-8、UTF-16就该上场了。它们被称作编码规则,能实现Unicode字符集可变长度的编码,也就是说计算机中实际存储的是编码后的Unicode值。由于常用的是UTF-8,所以先解释UTF-8与Unicode之间的编码。
- 对于单字节的符号。字节的第一位设为0,后面7位为这个符号的 Unicode码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
- 对于多字节的符号。最高位所在字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的用Unicode 码右端对齐填充。
Unicode码点(十六进制) | ?????UTF-8编码(二进制) |
---|---|
000000-00007F | 0xxxxxxx |
000080-0007FF | 110xxxxx 10xxxxxx |
000800-00FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
010000-10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
??既然UTF-8是最常使用的编码方式,那么为什么我们还要讨论UTF-16呢?因为Java采用的是UTF-16编码。哈哈哈,是不是很interesting。这时候我们再从UTF-8来看看Unicode的表示范围,即:[000000, 10FFFF],共可表示17 * 65535个字符。17指17的编码平面。UTF-16的编码规则如下(U代指Uniocde码点):
- 如果U < 0x10000,U的UTF-16编码就是U对应的16位无符号整数(为书写简便,下文将16位无符号整数记作WORD)。
- 如果U > 0xFFFF,我们先计算U'=U-0x10000,然后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。
??首先,U的最大值为0x10FFFF,减去0x10000后,U'的最大值是0xFFFFF,所以肯定可以用20个二进制位表示。例如:Unicode编码0x20C30,减去0x10000后,得到0x10C30,写成二进制是:0001 0000 1100 0011 0000。右端对齐替代模板,就得到:1101100001000011 1101110000110000,即0xD843 0xDC30。
??按照上述规则, 0x10000-0x10FFFF的UTF-16编码有两个WORD,第一个WORD的高6位是110110,第二个WORD的高6位是110111。可见,第一个WORD的取值范围是[11011000 00000000, 11011011 11111111],即[0xD800, 0xDBFF]。第二个WORD的取值范围是[11011100 00000000, 11011111 11111111],即 [0xDC00, 0xDFFF]。恰好Unicode标准规定:基本多语言平面([U+0000, U+FFFF])内,[U+D800, U+DFFF]里共2048个值不对应于任何字符,为代理区。也就是UTF-16正好利用了代理区来区分什么时候读4个字节,什么时候读2个字节。所以Java核心技术卷中强烈不建议使用char类型。因为一个char只代表一个WORD。
??综上,在一波又一波骚操作之后字符集、Unicode、UTF-8,UTF-16就不那么神秘了。
推荐阅读
- 一个人的碎碎念
- 野营记-第五章|野营记-第五章 讨伐梦魇兽
- Shell-Bash变量与运算符
- 清明,是追思、是传承、是感恩。
- 牛人进化+|牛人进化+ 按自己的意愿过一生
- 七老修复好敏感、角质层薄、红血丝
- 华为旁!大社区、地铁新盘,佳兆业城市广场五期!
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- 螃蟹和这些食物同吃,轻则腹泻、重则中毒!要小心哦~
- 八、「料理风云」