编码
我们计算机只能读懂01这两个字符,这和我们人类平时对文字的使用很不相同。如何在计算机里存储和表示文字,就涉及到了编码的知识。
计算机有哪些编码方式呢?
ASCII 码
我们知道,计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。
上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码,一直沿用至今。
ASCII 码一共规定了128个字符的编码,比如空格SPACE是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的一位统一规定为0。
这种编码方式完成了基础的编码,但是随着计算机的普及,我们需要在计算机里表示除了英文之外的内容,这128个字符显然是不够的。比如现在的这篇博客,里面的中文字符是如何表示的呢?除了中文,还有其他各国的语言字符,法文、希腊文、西班牙文…等等这些语言,需要大量的编码位置。
Unicode
正如上一节所说,世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。
可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是 Unicode,就像它的名字都表示的,这是一种所有符号的编码。
Unicode 当然是一个很大的集合,现在的规模可以容纳100多万个符号。Unicode定义了我们所能想到字符的二进制表示,可以说是很全面了。但是如何存储存储这些二进制呢?
直接存储?这是简单暴力的做法,因为在Unicode编码里a
对应的码点是97
,Unicode编码是U+0061
,二进制表示为1100001
, 中文远
字的码点是36828
,Unicode编码为U+8FDC
,二进制表示为1000111111011100
。a
只需要7个bit位,而远
却需要16个bit位。如果只用一个字节(8bit)显然是无法表示汉字远
的,但是如果用两个字节(16bit)那么在表示a
的时候前面要多出9个0,这无疑造成了空间上很大的浪费。
有了Unicode编码方式之后,还要想一个规则去保存这些字符。UTF-8
、UTF-16
、UTF-32
便是我们最常见的规则。
Unicode只是一个符号集,而UTF-8
、UTF-16
、UTF-32
是Unicode在计算机中的具体实现。不过在互联网中最最常用的还是UTF-8
。
Unicode的学名是”Universal Multiple-Octet Coded Character Set”,简称为UCS。UCS可以看作是”Unicode Character Set”的缩写。
UTF是“UCS Transformation Format”的缩写。‘8’是指用8位的bit块去表示一个字符。表示一个字符所需的字符块从1-4不等。
UTF-8
UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
UTF-8 的编码规则很简单,只有二条:
对于单字节的符号且小于7位的编码,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
对于大于7bit的编码,n字节的符号1字节按2字节来算(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
1st byte | 2nd byte | 3rd byte | 4th byte | 可用于表示字符的bit位个数 | 最大表示的Unicode 编码值 |
---|---|---|---|---|---|
0xxx xxxx | 7 | 007F hex(127) | |||
110x xxxx | 10xx xxxx | (5+6)=11 | 07FF hex(2047) | ||
1110 xxxx | 10xx xxxx | 10xx xxxx | (4+6+6)=16 | FFFF hex(65535) | |
1111 0xxx | 10xx xxxx | 10xx xxxx | 10xx xxxx | (3+6+6+6)=21 | 10FFFF hex(1,114,111) |
注:目前Unicode的编码最大为10FFFF。
这个规则已经定义好,如何根据Unicode编码,得出对应的UTF-8编码呢,来写一个JavaScript的程序来实现一下吧!
Unicode 与 UTF-8 之间的转换
如代码无法运行请点击这里
BMP (Basic Multilingual Plane)
Unicode 从U+0000
到U+FFFF
这个范围称为BMP,我们日常编码应该让代码保持在这个范围内。
其他编码方式
除了上述两种我们最最常接触的编码方式外,还有其他好多编码方式:
早期的计算机使用7位的ASCII编码,为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5。
GB2312
GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。
GBK
Reference
unicode官网
unicode format
UTF-8 的规则
字符编码笔记:ASCII,Unicode 和 UTF-8