1、Unicode是什么?
编码
Unicode(统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每一个字符设定了统一而且惟一的二进制编码,以知足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。spa
最先的字符编码是ASCII码,每一个字符是经过一个字节来表示的,可是随着计算机的不断发展,许多文字并不能用一个字节来表示,为了可以表示更多的语言文字,因此产生了Unicode,用两个字节来对字符进行编码,这样的话像中文、日语等也可以成功的在计算机上显示而且保存。在表示一个Unicode的字符时,一般会用“U+”而后紧接着一组十六进制的数字来表示这一个字符。code
2、UTF8/16/32分别是什么?orm
1) UTF8:UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式以下:blog
Unicode编码(十六进制) 图片 |
UTF-8 字节流(二进制)内存 |
000000-00007Funicode |
0xxxxxxxget |
000080-0007FFit |
110xxxxx 10xxxxxx |
000800-00FFFF |
1110xxxx 10xxxxxx 10xxxxxx |
010000-10FFFF |
11110xxx10xxxxxx10xxxxxx10xxxxxx |
UTF-8的特色:是对不一样范围的字符使用不一样长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码彻底相同。UTF-8编码的最大长度是4个字节。从上表能够看出,4字节模板有21个x,便可 以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。
2)UTF16:UTF-16是Unicode字符编码五层次模型的第三层:字符编码表(Character Encoding Form,也称为 "storage format")的一种实现方式。即把Unicode字符集的抽象码位映射为16位长的 整数(即码元)的序列,用于数据存储或传递。Unicode字符的码位,须要1个或者2个16位长的码元来表示,所以这是一个变长表示。
3)UTF32:UTF-32 (或 UCS-4)是一种将Unicode字符编码的协定,对每个Unicode码位使用刚好32位元。其它的Unicode transformation formats则使用不定长度编码。由于UTF-32对每一个字符都 使用4字节,就空间而言,是很是没有效率的。特别地,非基本多文种平面的字符在大部分文件中一般很罕见,以至于它们一般被认为不存在占用空间大小的讨论,使得UTF-32一般会是其它 编码的二到四倍。虽然每个码位使用固定长定的字节看似方便,它并不如其它Unicode编码使用得普遍。
3、Unicode和UTF8/16/32之间的关系
首先要注意的是unicode是编码字符集,而UTF-八、UTF-1六、UTF-32是字符集编码。下面我来具体解释一下:好比汉字的”汉”,在unicode中,汉”的unicode值为0x6C49。问:把这个”汉”字保存到计算机中(硬盘、内存),机器码是多少呢? 学过《计算机组成原理》的人都知道,计算机内部存储的形式都是0101的二进制数字串。”汉”字保存在计算机里确定也是0101的数字串。”汉”的unicode值是0x6C49,转化为2进制 1101100 01001001,那么把这个”汉”字保存到计算机中也是 1101100 01001001 吗?其实并非这样的,答案取决于用到的字符集编码是哪一种 好比你用到的字符集编码是UTF-8,那么”汉”字在计算机内部保存的值为0xE6B189,也就是111001101011000110001001,能够看到”汉”字变成了3个字节。UTF-8用1-4个字节来保存unicode编码的字符。 而若是用UTF-16来保存,那么”汉”字仍为仍为0x6C49,也就是 1101100 01001001。UTF-16只能是选两字节或四字节来保存字符 而UTF-32就是把全部的字符都用32bit也就是4个字节来表示。 因此这就是编码字符集和字符集编码的区别。
UTF,即Unicode Transformer Format,是Unicode代码点(code point)的实际表示方式,按其基本长度所用位数分为UTF-8/16/32。它也能够认为是一种特殊的外部数据编码,但可以与Unicode代码点作一一对应。也就是其实从本质上说,UTF-八、UTF-1六、UTF-32 都是 Unicode 的一种实现,只是实现的方式不一样罢了。因此UTF8/16/32是Unicode的衍生,和Unicode是息息相关的。接下来从这三个UTF开始分析和Unicode的关系。
一、UTF-32
这个就是字符所对应编号的整数二进制形式,四个字节。这个就是直接转换。 好比马的 Unicode 为:U+9A6C,那么直接转化为二进制,它的表示就为:1001 1010 0110 1100。
这里须要说明的是,转换成二进制后计算机存储的问题,咱们知道,计算机在存储器中排列字节有两种方式:大端法和小端法,大端法就是将高位字节放到低地址处,好比 0x1234, 计算机用两个字节存储,一个是高位字节 0x12,一个是低位字节 0x34,它的存储方式为下:
UTF-32 用四个字节表示,处理单元为四个字节(一次拿到四个字节进行处理),若是不分大小端的话,那么就会出现解读错误,好比咱们一次要处理四个字节 12 34 56 78,这四个字节是表示 0x12 34 56 78 仍是表示 0x78 56 34 12?不一样的解释最终表示的值不同。
咱们能够根据他们高低字节的存储位置来判断他们所表明的含义,因此在编码方式中有 UTF-32BE 和 UTF-32LE,分别对应大端和小端,来正确地解释多个字节(这里是四个字节)的含义。
UTF-16 使用变长字节表示
① 对于编号在 U+0000 到 U+FFFF 的字符(经常使用字符集),直接用两个字节表示。
② 编号在 U+10000 到 U+10FFFF 之间的字符,须要用四个字节表示。
一样,UTF-16 也有字节的顺序问题(大小端),因此就有 UTF-16BE 表示大端,UTF-16LE 表示小端。
UTF-8 就是使用变长字节表示,顾名思义,就是使用的字节数可变,这个变化是根据 Unicode 编号的大小有关,编号小的使用的字节就少,编号大的使用的字节就多。使用的字节个数从 1 到 4 个不等。
UTF-8 的编码规则是:
① 对于单字节的符号,字节的第一位设为 0,后面的7位为这个符号的 Unicode 码,所以对于英文字母,UTF-8 编码和 ASCII 码是相同的。
② 对于n字节的符号 (n>1),第一个字节的前 n 位都设为 1,第 n+1 位设为 0,后面字节的前两位一概设为 10,剩下的没有说起的二进制位,所有为这个符号的 Unicode 码 。
举个例子:好比说一个字符的 Unicode 编码是 130,显然按照 UTF-8 的规则一个字节是表示不了它(由于若是是一个字节的话前面的一位必须是 0),因此须要两个字节(n = 2)。
根据规则,第一个字节的前 2 位都设为 1,第 3(2+1) 位设为 0,则第一个字节为:110X XXXX,后面字节的前两位一概设为 10,后面只剩下一个字节,因此后面的字节为:10XX XXXX。
因此它的格式为 110XXXXX 10XXXXXX 。
下面咱们来具体看看具体的 Unicode 编号范围与对应的 UTF-8 二进制格式
那么对于一个具体的 Unicode 编号,具体怎么进行 UTF-8 的编码呢?
首先找到该 Unicode 编号所在的编号范围,进而能够找到与之对应的二进制格式,而后将该 Unicode 编号转化为二进制数(去掉高位的 0),最后将该二进制数从右向左依次填入二进制格式的 X 中,若是还有 X 未填,则设为 0 。
好比:“马”的 Unicode 编号是:0x9A6C,整数编号是 39532,对应第三个范围(2048 - 65535),其格式为:1110XXXX 10XXXXXX 10XXXXXX,39532 对应的二进制是 1001 1010 0110 1100,将二进制填入进去就为:
11101001 10101001 10101100 。
因为 UTF-8 的处理单元为一个字节(也就是一次处理一个字节),因此处理器在处理的时候就不须要考虑这一个字节的存储是在高位仍是在低位,直接拿到这个字节进行处理就好了,由于大小端是针对大于一个字节的数的存储问题而言的。
从上面的讲解也能看出来,UTF8/16/32都是Unicode的一种实现方式。