ASCII 和 Unicode

字符集和字符编码的区别、ASCII字符集&编码、Unicode字符集、UTF-8字符编码、UTF-16、UCS-2字符编码、UTF-32、UCS-4字符编码。

字符集、字符编码

百度百科:

字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等;
字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等;
计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字;

知乎某回答:

字符集:为每一个「字符」分配一个唯一的 ID(学名为码位/码点/Code Point);
字符编码:将「码位转换字节序列的规则(编码/解码可以理解为加密/解密的过程);

个人理解:

字符集:每个字符用一个唯一的数字来表示,这样的集合称为字符集,或者称为字符表示方法
字符编码:将字符集存储在计算机内存/磁盘、网络的一种存储方案,或者称为字符存储方案

ASCII字符集&编码

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统;
它主要用于显示现代英语,而其扩展版本 EASCII 则可以勉强显示其他西欧语言;它是现今最通用的单字节编码系统(但是有被 Unicode 追上的迹象),并等同于国际标准 ISO/IEC 646;

ASCII字符集:主要包括控制字符(回车键、退格、换行键等)可显示字符(英文大小写字符、阿拉伯数字和西文符号)
ASCII字符编码:将 ASCII 字符集转换为计算机可以接受的数字系统的数的规则;
使用 7 位(bits)表示一个字符,共 128 字符;但是 7 位编码的字符集只能支持 128 个字符,为了表示更多的欧洲常用字符对 ASCII 进行了扩展,ASCII 扩展字符集使用 8 位(bits)表示一个字符,共 256 字符;

ASCII的局限性:
ASCII 的最大缺点是只能显示 26 个基本拉丁字母、阿拉伯数目字和英式标点符号,因此只能用于显示现代美国英语(而且在处理英语当中的外来词如 naïve、café、élite 等等时,所有重音符号都不得不去掉,即使这样做会违反拼写规则);
而 EASCII 虽然解决了部份西欧语言的显示问题,但对更多其他语言依然无能为力;

Unicode字符集

有两个机构试图对全世界所有的文字字符进行统一编码:

(1) 国际标准化组织(ISO),他们于 1984 年创建 ISO/IEC JTC1/SC2/WG2 工作组,试图制定一份“通用字符集”(Universal Character Set,简称UCS),并最终制定了ISO 10646 标准;
(2) 统一码联盟,他们由 Xerox、Apple 等软件制造商于 1988 年组成,并且开发了 Unicode 标准(The Unicode Standard);

1991 年前后,两个项目的参与者都认识到,世界不需要两个不兼容的字符集;于是,它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作;
从 Unicode 2.0 开始,Unicode 采用了与 ISO 10646-1 相同的字库和字码;ISO 也承诺,ISO 10646 将不会替超出 U+10FFFF 的 UCS-4 编码赋值,以使得两者保持一致;
两个项目仍都独立存在,并独立地公布各自的标准;不过由于 Unicode 这一名字比较好记,因而它使用更为广泛;

Unicode 编码点分为 17 个平面(plane),每个平面包含 2^16(即 65536)个码位(code point);17 个平面的码位可表示为从 U+xx0000 到 U+xxFFFF,其中 xx 表示十六进制值 0x00 到 0x10,共计 17 个平面;

UTF-32、UCS-4

在 Unicode 与 ISO 10646 合并之前,ISO 10646 标准为“通用字符集”(UCS)定义了一种 31 位的编码形式(即 UCS-4 ),其编码固定占用4个字节,编码空间为 0x00000000~0x7FFFFFFF(可以编码 20 多亿个字符);

UCS-4 有 20 多亿个编码空间,但实际使用范围并不超过 0x10FFFF,并且为了兼容 Unicode 标准,ISO 也承诺将不会为超出 0x10FFFF 的 UCS-4 编码赋值;
由此 UTF-32 编码被提出来了,它的编码值与 UCS-4 相同,只不过其编码空间被限定在了 0~0x10FFFF 之间;因此也可以说:UTF-32 是 UCS-4 的一个子集

UTF-16、UCS-2

除了 UCS-4,ISO 10646 标准为“通用字符集”(UCS)定义了一种 16 位的编码形式(即 UCS-2 ),其编码固定占用2个字节,它包含 65536 个编码空间(可以为全世界最常用的 63K 字符编码,为了兼容 Unicode,0xD800-0xDFFF 之间的码位未使用);

但俩个字节并不足以正真地“一统江湖”,于是 UTF-16 诞生了,与 UCS-2 一样,它使用2个字节为全世界最常用的 63K 字符编码,不同的是,它使用4个字节对不常用的字符进行编码UTF-16属于变长编码

UTF-16 可看成是 UCS-2 的父集
在没有辅助平面字符(surrogate code points)前,UTF-16 与 UCS-2 所指的是同一的意思;但当引入辅助平面字符后,就称为 UTF-16 了;
现在若有软件声称自己支持 UCS-2 编码,那其实是暗指它不能支持在 UTF-16 中超过 2 字节的字集;对于小于 0x10000 的 UCS 码,UTF-16 编码就等于 UCS 码;

UTF-8

从前述内容可以看出:无论是 UTF-16/32 还是 UCS-2/4 ,一个字符都需要多个字节来编码,这对那些英语国家来说多浪费带宽啊!(尤其在网速本来就不快的那个年代);

由此,UTF-8 产生了;在 UTF-8 编码中,ASCII码中的字符还是 ASCII 码的值,只需要1个字节表示,其余的字符需要2字节、3字节或4字节来表示;

UTF-8 的编码规则:
(1) 对于 ASCII 码中的符号,使用单字节编码,其编码值与 ASCII 值相同;其中 ASCII 值的范围为 0~0x7F,所有编码的二进制值中第一位为 0(这个正好可以用来区分单字节编码和多字节编码);

(2) 其它字符用多个字节来编码(假设用 N 个字节),多字节编码需满足:第一个字节的前 N 位都为 1,第 N+1 位为 0,后面 N-1 个字节的前两位都为 10,这 N 个字节中其余位全部用来存储 Unicode 中的码位值;如下表:

字节数 Unicode UTF-8编码
1 000000 - 00007F 0xxxxxxx
2 000080 - 0007FF 110xxxxx 10xxxxxx
3 000800 - 00FFFF 1110xxxx 10xxxxxx 10xxxxxx
4 010000 - 10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

总结、引用

(1) Unicode 属于字符集,不属于编码,UTF-8、UTF-16 等是针对 Unicode 字符集的编码;

(2) UTF-8、UTF-16、UCS-2、UTF-32、UCS-4 对比:

编码方案 UTF-8 UTF-16 UCS-2 UTF-32 UCS-4
编码空间 0 - 10FFFF 0 - 10FFFF 0 - FFFF 0 - 10FFFF 0 - 7FFFFFFF
最少字节数 1 2 2 4 4
最多字节数 4 4 2 4 4
是否依赖字节序

字节顺序标记(英语:byte-order mark,BOM),用来标识 Unicode/UCS 文本文件中的字节序是大端还是小端;
BOM 只适用于UTF-16/UCS-2UTF-32/UCS-4,UTF-8 不需要所谓的 BOM 标识,UTF-8 没有所谓的字节序问题;

相关参考:
Java 中的 Unicode 支持以及 UTF-16BE 编码(内码)
细说:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4
字符集和字符编码(Charset & Encoding)
UTF-16 维基百科,自由的百科全书
字节顺序标记BOM 维基百科,自由的百科全书