编码

我们计算机只能读懂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,二进制表示为1000111111011100a只需要7个bit位,而却需要16个bit位。如果只用一个字节(8bit)显然是无法表示汉字的,但是如果用两个字节(16bit)那么在表示a的时候前面要多出9个0,这无疑造成了空间上很大的浪费。

有了Unicode编码方式之后,还要想一个规则去保存这些字符。UTF-8UTF-16UTF-32便是我们最常见的规则。

Unicode只是一个符号集,而UTF-8UTF-16UTF-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 的编码规则很简单,只有二条:

  1. 对于单字节的符号且小于7位的编码,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。

  2. 对于大于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+0000U+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