从一个问题提及算法
为何计算字符串的长度的时候会把中文当作2个字符,英文当成一个字符来计算?数组
在计算机中,字符是一个信息单位。简单来讲就是一个汉字或者一个英文,一个标点符号。网络
顾名思义,字符集就是字符的集合。编码
字符编码就是把字符集中的字符编码为指定集合中的某一对象,以便在计算机中存储和经过网络传递。3d
是指一个已编码的文本中具备最短比特组合的单元。对于UTF-8来讲码元是8比特长。对于UTF-16来讲,码元是16比特长。对于UTF-32来讲,码元是32比特长。代理
字符编码由如下几个关键元素构成:code
全称是American Standard Code for Information Interchange,译作美国信息交换标准代码。这套字符集在1967年被正式公布。orm
它一共包含128种字符,其中33个控制字符,95个可显示的字符。正好是一个字节的低7位,最高位置0。cdn
下图是一个ASCII码的表格: 对象
刚开始计算机只在美国使用,因此128个字符是够用的,可是随着科技的发展欧洲的国家也开始使用上了计算机。这时候出现了问题,128个字符不够用了。好比法语中有注音符号,因而一些欧洲国家决定利用字节中闲置的最高位编入新的符号。 这样就在ASCII码的基础上,既保证了对ASCII码的兼容性,又补充扩展了新的字符,因而就称之为Extended ASCII(扩展ASCII)码,简称EASCII码。
在EASCII码中,当第一个比特位(即字节的最高位)为0时,仍表示以前那些经常使用的ASCII字符(实际的二进制编码为0000 0000 ~ 0111 1111,对应的十进制就是0~127),而为1时就表示补充扩展的其余衍生字符(实际的二进制编码为1000 0000 ~ 1111 1111,对应的十进制就是128~255)。
EASCII的扩展部分以下图: [image:DA4EFEE5-575B-4D69-AB85-0D6A0963052E-55654-00029E64D82D4B45/18408A67-1AF3-4473-AE8A-E7E6DE1C355B.png]
可是有这样想法的国家有不少,因此还有另外一套标准就是ISO 8859。
ISO 8859 是一组字符集的总称,其下共包含了15个字符集,即ISO 8859-n ,其中n=1,2,3…11,13,14,15,16
这两种编码方式都是前128位兼容ASCII码,后128位本身定义。
后来计算机进入了中国,EASCII码也不够用了。要知道,汉字是世界上包含符号最多的文字。因而⌈中国国家标准总局⌋(现已改名为⌈国家标准化管理委员会⌋)在1981年,正式制订了中华人民共和国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,项目代号为GB 2312 或 GB 2312-80(GB为国标汉语拼音的首字母),此套字符集于当年的5月1日起正式实施。
GB2312编码为了不与ASCII字符编码(0~127)相冲突,规定表示一个汉字的编码(即汉字内码)的字节其值必须大于127(即字节的最高位为1),而且必须是两个大于127的字节连在一块儿来共同表示一个汉字(GB2312为双字节编码),前一字节称为高字节,后一字节称为低字节;而一个字节的值若小于127(即字节的最高位为0),天然是仍表示一个原来的ASCII字符(ASCII为单字节编码)。
所以,能够认为GB2312是对ASCII的中文扩展(即GB2312与ASCII相兼容),正如EASCII是对ASCII的欧洲文字扩展同样。
不过,很显然的是,GB2312与EASCII码的128~255这段扩展部分所表示的字符是不一样的。也就是说,GB2312与EASCII虽然都兼容ASCII,但GB2312并不兼容EASCII的扩展部分。
事实上,目前世界上除ASCII以外的其它通行的字符编码方案,基本上都兼容ASCII,但相互之间并不兼容。
GB2312中,多是出于显示上视觉美观的考虑,除汉字以外的682个字符中,甚至包括了ASCII里原本就有的数字、标点、字母等字符。也就是说,这些ASCII里原来就有的单字节编码的字符,又再编了两个字节长的GB2312编码版本。这682个字符就是常说的“全角”字符,而这682个字符中所对应的ASCII字符就被称之为“半角”字符。
上面说了这么多种编码,每一个国家都有本身的编码标准,以便能在计算机上正确的显示本身国家的符号。可是不一样国家地区互相不能正确显示。因此有2个组织来尝试指定统一的编码标准。
1991年,两个组织共同的工做成果Unicode 1.0正式发布,不过Unicode 1.0并不包含CJK字符(即中日韩)。
1993年时,包含CJK的Unicode 1.1已经发布了,因而在同一年,中国大陆制定了几乎等同于Unicode1.1的GB13000.1-93国家编码标准(简称GB13000)。是的,你没听错,中华人民共和国信息产业部把Unicode里的全部东东拿过来,而后本身从新修订发布了下,改成了国家标准GB13000。此标准等同于 ISO/IEC 10646.1:1993和Unicode 1.1。
GB2312 基本覆盖了中国大陆99%以上的使用频率,基本知足了汉字的计算机处理须要。但对人名,生僻字等并不能处理。
因而,利用GB2312未使用的码点空间,收录这些字符,于1995年又发布了《汉字内码扩展规范(GBK)》。其中K是扩展的意思。
GBK跟GB2312同样是双字节编码,然而,GBK只要求第一个字节即高字节是大于127就固定表示这是一个汉字的开始(0~127固然表示的仍是ASCII字符),再也不要求第二个字节即低字节也必须是127号以后的编码。这样,做为一样是双字节编码的GBK才能够收录比GB2312更多字符。
因此GB系列的编码方案中,一个汉字是由2个字节组成,一个英文是由一个字节组成。
顾名思义,UCS-2就是用两个字节编码,UCS-4就是用4个字节(实际上只用了31位,最高位必须为0)编码
是Unicode的一种实现方式。是一种可变长度的编码方式。它可使用1~4个字节表示一个符号,根据不一样的符号来变化字节长度。 编码规则:
编码实现:
根据编码规则,同理能够推出解码规则:
举个例子: 0xxxxxxx 110xxxxx 10xxxxxx 1110xxxx 10xxxxxx 10xxxxxx 1110xxx 10xxxxxx 10xxxxxx 10xxxxxx
也是Unicode的一种实现方式。是把Unicode字符集的抽象码位映射为16位长的整数(码元)的序列。须要1~2个16位长的码元来表示,因此这是一个边长表示。
Unicode的编码空间从U+0000到U+10FFFF,共有1,112,064个码位(code point)可用来映射字符。Unicode的编码空间能够划分为17个平面(Plane),每一个平面包含2^16(65536)个码位。17个平面的码位可表示为从U+xx0000 到 U+xxFFFF,其中xx表示十六进制从00到10。第一个平面称为基本多语言平面(Basic Multilingual Plane, BMP),或称第零平面(Plane 0)。其余平面称为辅助平面(Supplementary Planes)。基本多语言平面内,从U+D800到U+DFFF之间的码位区块是永久保留不映射到Unicode字符。UTF-16就利用保留下来的0xD800-0xDFFF区段的码位来对辅助平面的字符的码位进行编码。
编码规则: U+0000 ~ U+D7FF 和 U+E000 ~ U+FFFF 这个范围即基本多语言平面(Basic Multilingual Plane, BMP),包含了最经常使用的字符,包含的码位范围是U+0000 到 U+FFFF,只须要一个16位的码元便可表示。
U+10000 ~ U+10FFFF 其它平面(叫作辅助平面,Supplementary Planes)中的码位,在UTF-16中被编码为一对16比特长的码元(即32bit,4Bytes),称做代理对(surrogate pair),具体方法是:
上述算法可理解为:辅助平面中的码位从U+10000到U+10FFFF,共计FFFFF个,即2^20=1,048,576个,须要20位来表示。若是用两个16位长的整数组成的序列来表示,第一个整数(称为前导代理)要容纳上述20位的前10位,第二个整数(称为后尾代理)容纳上述20位的后10位。还要能根据16位整数的值直接判明属于前导整数代理的值的范围(2^10=1024),仍是后尾整数代理的值的范围(也是2^10=1024)。所以,须要在基本多语言平面中保留不对应于Unicode字符的2048个码位,就足以容纳前导代理与后尾代理所须要的编码空间。这对于基本多语言平面总计65536个码位来讲,仅占3.125%.
编码规则实现:
根据UTF-16的编码规则,同理能够获得解码规则,下图是从Swift源码中截取的UTF-16的解码代码: [image:69D26150-1CDC-4E9D-B94E-916136C27353-55654-0002535098FC388A/46208888-62B3-4137-95AE-A697AFD5B43A.png]
举个例子: 例如U+10437编码(𐐷)
UTF-16比起UTF-8,好处在于大部分字符都以固定长度(2字节)存储,可是UTF-16没法兼容ASCII码。
思考问题:
一、Unicode与UTF-8 16 有什么区别?
二、为何UTF-8不须要专门指明字节序?
三、为何计算字符个数会把英文当成一个中文当成两个?
四、咱们常说的Unicode编码指的是什么?