网站开发中常常会被乱码问题困扰。知道文件编码错误会致使乱码,但对其中的原理却知之甚少。偶然从某篇文章了解了Unicode,发现从这条线出发也牵引出了一系列缺失的知识点。经过研读文章,基本了解了一些之前不明白的问题,因此整理了几篇,从几个角度介绍下Unicode, 并聊聊一些相关的问题。html
上世纪60年代,美国人采用了一种编码来表示英语以及各类符号,该编码方式只有一个字节,能表示256(2^8)个字符。至今为止才定义了128个字符。包括33个控制字符和95个可显示字符,这些可显示字符涵盖了大小写英文字母和一些符号,这就是大名鼎鼎的ASCII编码。浏览器
然而随着计算机的发展,各个国家的语言符号多不胜数,在中国光中文字符就有7000多个,还不包括繁体中文,ASCII显然没法知足这么多字符编码需求。因此中国人本身创造了一种字符编码,每一个汉字和符号用两个字节来表示。第一个字节称为"高位字节",第二个字节称为"低位字节"。高位字节使用了0xA1 - 0xF7, "低位字节"使用了0xA1 - 0xFE。同时该编码方式兼容了ASCII的编码,对于小于127的字符即0x00 - 0x7F的字符予以保留。这种编码方式就是中文编码GB 2312。网站
然而GB 2312能表示的文字也比较有限,对于一些人名,古汉语和繁体字也无能为力。因此咱们改进了GB 2312的编码方式,扩展了GB 2312 中不使用的字节,使其同时包括了GB2312的全部内容,又新增了近20000个新的汉字,包括繁体字。该编码就是咱们熟悉的GBK。后来因为又加了少数名族的文字,又推出了GB18030,用于取代GBK。而目前为止咱们使用最普遍的中文编码仍是GBK。编码
再后来,因为不一样的国家地区之间都使用不一样的编码,致使计算机文件的读取都须要安装不一样的解码软件。常常照成文件读取乱码。因而有一些组织决定制定出一个方案,经过统一的编码解决这个难题。因而其中一个团队发明了UCS编码,还有另外一个团队发明了Unicode。后来二者达成一致,只发布一套字符集,那就是Unicode 。而UCS的码点将与Unicode保持一致。spa
Unicode最初规定用16位的编码空间,这16位编码空间称为统一码。这样理论上一共最多有2^16(65536)个字符。基本知足各类语言的使用。实际上当前版本的统一码并未彻底使用这16位编码,而是保留了大量空间以做为特殊使用或未来扩展。设计
目前的Unicode字符分为17组编排,每组称为一个平面(Plane),而每平面拥有65536(即2^16)个码点。上述16位统一码字符称为基本多文种平面(BMP),写成16进制就是从U+0000到U+FFFF。 剩下还有16个辅助平面(SMP),码点范围从U+010000一直到U+10FFFF。这17个平面结合起来至少须要占据21位的空间(2^16 x 2^5),也就是差很少3个字节(24位),而辅助平面其实是用4个字节表示,方便之后向后扩展。code
上面讲到的几种编码都是编码方式,规定了从码点到字符的映射关系,例如 Unicode中U+0061 对应的就是小写字母 "a", 咱们能够在浏览器控制台中输入码点查找对应的字符:orm
UTF
Unicode的实现方式不一样于编码方式。一个字符的Unicode编码是肯定的。可是在实际传输过程当中,因为不一样系统平台的设计不必定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不一样。Unicode的实现方式称为Unicode转换格式(Unicode Transformation Format,简称为UTF)。htm
网页开发中比较熟悉和经常使用的编码实现是UTF-8。那么这种实现方式有什么优点呢?UTF-8是一种变长的编码方法。字符长度从1字节到4字节不等。最前面的128个字符,只使用1个字节表示,延续了ASCII的用法。其余分段的字节数以下:blog
计算机在读取数据的时候都是从高位到地位或从地位到高位。当计算机读到一个3字节字符时,怎么判断是输出1位字符,仍是继续读取接下来的2位并合并为一个字符呢?这就要涉及到UTF-8的具体实现了。
UTF-8是这样作的:
单字节的字符,字节的第一位设为0,对于英语文本,UTF-8码只占用一个字节,和ASCII码彻底相同;
n个字节的字符(n>1),第一个字节的前n位设为1,第n+1位设为0,后面字节的前两位都设为10,这n个字节的其他空位填充该字符unicode码,高位用0补足。
这样就造成了以下的UTF-8标记位:
0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
当读到第一位时,发现是0开头,就读一个字节。发现是110,就读两个字节,发现是1110就读三个字节,以此类推,再根据Unicode规则找到对应的符号输出。这种变长的编码方式,能根据字符采用不一样位数的码点,可以有效减小文件的体积。
若是采用Unicode的编码方式直接做为实现方法。那么每一个字符都是定长的码点,对于只须要一个字节的字符,须要在前面补0. 这样就照成了空间的浪费,文件就会变大。
UTF编码除了UTF-8,还有UTF-16:最小的码点为2个字节;UTF-32:每一个码点固定用4个字节表示。因为UTF-32传输场进下会照成文件空间浪费,HTML5标准规定,网页不得编码成UTF-32。
关于Unicode的介绍就到这。UCS的相关知识,将在下一章结合JavaScript一块儿讲到。
参考文章:
https://zh.wikipedia.org/wiki
http://www.ruanyifeng.com/blo...
https://www.zhihu.com/questio...