The World of TomasRan

关于字符集、编码字符集和字符编码

准备好开始

我不是偏执于概念,只是很多时候只有对一个词汇或者术语的定义有着明确的把握之后才会自信地去使用它们。我觉得这不至于是一件钻牛角尖的坏事情,能够清晰地辨别它们或者准确地使用它们至少令自己心里踏实,不会迷惑于其它叙述者的七嘴八舌。

因此,在比较充分地接触编码这一堆看上去令人头晕脑胀的事情之前,我想有必要先明确几个概念,相信我,这将有助于我们理清思绪。

字符集

顾名思义,字符集是字符的集合。

字符是什么?世界上各个国家的语言、符号、表情等都可以视为字符。在计算机界,一个字符是一个单位的字形、类字形单位或符号的基本信息。

我所要强调的重点,是在计算机中,存在着大量不同的字符集:ASCII字符集、Unicode字符集、ISO字符集等等,它们的集合元素不尽相同,包含的字符有所差别,这和以信仰为主题而诞生的不同宗教、以工作为主题而出现的不同行业别无二致。它们都属于字符集这个大概念,但是集合元素有差别。

那么为什么会有这种差别呢?作为一个中国人,我想要计算机支持的字符集里包含所有的中文,理所当然;作为一个美国人,我想要计算机支持的字符里包含所有英文字母,无可厚非;又或者只想任性地定义一套火星文,无力吐槽。假设彼此都不想要支持或包含对方的字符,这样就诞生了不同的字符集。因此,不同设计者的设计目标的差异直接导致了字符集的差别。

为什么不统一一个包罗万象的字符集呢?统一的过程是漫长的,过程中的分歧也是不可避免,不过好在现在我们已经走上了这条路:Unicode字符集。

字符集只是将一堆字符收集起来,划了个圈子,起了个名。

编码字符集

那么,编码字符集是什么?我们现在准备了一个字符集,然后给字符集中的每个字符映射一个抽象的数字,这就是编码字符集。简单的说,就是给字符集中的字符一一编号。

以下是Unicode字符集的编号,具体可以参见 Unicode字符编码表

Unicode字符编码表

编码字符集建立了字符和数字码的一一映射关系。

字符编解码

那么,现在困惑来了,我们常说的字符编码、字符解码是什么?

编码字符集是将字符集中的字符和数字建立对应关系,构成了一张映射表。它就静静地躺在那里,无声无息,并不会主动去做些什么。而我们则希望计算机在存储、发送和显示字符的时候能得到正确的结果。那么既然字符集本身无能为力,我们就需要写一套规则、一堆代码去主动处理字符的存储、发送和显示。这一步过程就是字符的编码和解码。

计算机存储、发送的都是二进制流数据,明白这一点很重要。我们的问题就是如何将这些二进制数据流解析成字符,或者如何将字符用二进制数据表示。

下面就通过ASCII码字符集(所谓的字符编解码,都是针对某个特定的字符集)对应的编解码方案来解释一下这个过程:

ASCII码表

上表是ASCII码的编码字符集,一张映射表,ASCII码因为字符数量的稀少,用8bit(通常说一个字节,但注意一个字节并不是总等于8bit,只是现在大部分计算机是这样而已)就可以完全表示。

ASCII码的编码过程很简单,只需要根据以上这张映射表查找到对应的字节,将该字节进行存储就完成了编码过程。例如字符“A”,存储到文件中就是 “01000001”。so easy,不是吗?ASCII码字符编码就是这样简单的查表过程。解码过程也很简单,对二进制数据流按照8bit进行划分,然后也是根据以上的映射表找到对应的字符即可,例如 “0011000001010000”,划分为 “00110000” 和 “01010000”,查表可得依次是“0”、“P”。

ASCII码字符集的这一套编解码方案简单的人神共愤。稍微复杂的编码方式例如针对Unicode字符集的UTF-8、UTF-16、UTF-32编码后续再论。重点是,现在我们应该能够清楚地区分字符集、编码字符集和字符编码,并且明白一种字符集只有一套编码字符集,但可以有多种字符编码方案。道理显而易见。

我们通常所说的编码方式就是针对这各种字符集的不同编码方案,当再听到UTF-8,UTF-16,Big5,ISO-8859-1,GB2312等等乱七八糟的编码方式时,可以不用再感到恐慌,而是轻描淡写的一句:“哦,不过是另外一种字符集的另一种编码方式而已”。