乐趣区

字符编码计算机的巴别塔

首发于 字符编码:计算机的巴别塔

巴别塔:《圣经·旧约·创世记》第 11 章宣称,当时人类联合起来兴建希望能通往天堂的高塔;为了阻止人类的计划,上帝让人类说不同的语言,使人类相互之间不能沟通,计划因此失败,人类自此各散东西。此故事试图为世上出现不同语言和种族提供解释。

我们曾经在 HTTP 的响应头中见到过 Content-Type:text/html; charset=utf-8,也曾在HTML 文件中见到过 <meta charset="utf-8">。它们都是用于声明字符编码为utf-8。那么utf-8 到底是什么?这要从计算机的起源说起。

最早的计算机是机械式继电器计算机,通过继电器的开关状态来表示 0 和 1。后来的电子管计算机、晶体管计算机、集成电路计算机都继承了这一设定,这也是为什么计算机以二进制来存储数据。

人类发明计算机的目的是处理数据,而绝大多数数据都是文本形式的,所以要把这些文本转换为计算机可识别的二进制数据,再把计算机处理过的二进制数据转换为人类可识别的文本。这个二进制和文本的对照表就是字符集。

ASCII

美国人发明了最早的现代计算机。所以美国人最初制定了 ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)来保存控制码、空格、标点符号、数字、大小写字母。计算机的一个字节可以组合出 2^8 种不同的状态。ASCII 使用了 128 个状态。

编号从 0 开始的 32 种状态分别规定了特殊的用途,这些 0×20 以下的字节状态称为”控制码”。

随着世界各地的不同国家开始使用计算机,为了可以在计算机中使用 ASCII 中没有制定的文字,在 128 至 255 号之后的状态来表示这些新的字母、符号。这些字符集被称“扩展字符集”。

GB2312、GBK 和 BIG5

ASCII中是没有汉字的,而常用简体汉字就有几千个。所以中国制定了 GB2312(GB 是国标的拼音缩写)。GB2312 规定:一个小于 127 的字符的意义与原来相同,但两个大于 127 的字符连在一起时,就表示一个汉字。GB2312收录了 6763 个常用汉字。这也是为什么在以前一个汉字算两个英文字符的原因。

但是汉字有那么多,GB2312中并不包含生僻字,所以还是需要扩展。扩展之后的编码方案被称为 GBK 标准,GBK包括了 GB2312 的所有内容,同时又增加了近 20000 个新的汉字(包括繁体字)和符号。

当时同文同种的港台同胞们也制定一套编码标准 BIG5,这套标准和GB2312/GBK 并不兼容。而世界各地其他国家也制定了自己的标准。虽然本地使用没有问题,然而在网络中由于字符集不兼容,大家谁也看不懂别人的编码,互相访问就会出现乱码。我们仿佛进入了巴别塔被摧毁后的世界。

unicode

为解决这个问题,ISO(国际标谁化组织)制定了通用字符集:“Universal Multiple-Octet Coded Character Set”,简称UCS,又称unicode

ISO规定必须用 4 个字节来统一表示所有的字符,对于 ASCII 里的那些“半角”字符,unicode包持其原编码不变,只是将其长度由原来的 8 位扩展为 32 位,高位全部置为 0,而其他语言的字符则全部重新统一编码。这个字符集的编码方式称为UTF-32(32-bit UCS Transfer Format)。

有 2^32 个状态的 unicode 以后会不会也不够用?以前我们还觉得 IPv4 的地址用不完呢。但人类之所以伟大,原因之一就在于我们能够通过无穷的创造力解决各种问题。

如果按照 unicode 规定,每个符号用 4 个字节表示,那么文本文件的大小会因此大出二三倍,在存储和传输上就会很浪费。这也是 unicode 在很长一段时间内无法推广的原因。

UTF-8

直到 UTF-8 的出现。UTF-8(8-bit Unicode Transformation Format)是一种针对 unicode 的可变长度字符编码。它可以用来表示 unicode 标准中的任何字符,且其编码中的第一个字节仍与 ASCII 兼容,这使得原来处理 ASCII 字符的软件无须或只须做少部份修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持 UTF-8 编码。

UTF- 8 使用一至四个字节为每个字符编码:

unicode是字符集,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
- 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
- 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

最终,人类通过 unicode 建立了计算机世界的巴别塔。

退出移动版