字符集(Character Set)和编码(Encoding)的历史演化
字符集(Character Set)和编码(Encoding)是两个相关但不同的概念,它们在计算机和信息技术领域用于处理文本数据。
-
字符集(Character Set):
- 字符集是一种定义了一组字符、符号和控制符号的集合,这些字符通常用于书写和表示文本信息。字符集包括字母、数字、标点符号、特殊符号、控制字符等。
- 字符集定义了字符的抽象概念,即哪些字符可以在文本中使用。字符集通常以名称标识,如ASCII、Unicode、ISO 8859-1等。
- 字符集并未规定如何在计算机内部表示这些字符,它只是一个字符的逻辑概念。不同字符集可以包含不同的字符,因此选择正确的字符集对于文本的正确解释和显示至关重要。
-
编码(Encoding):
- 编码是一种将字符集中的字符映射到二进制数据的方式。它确定了如何在计算机内部表示和存储字符。编码将字符映射到唯一的编码值或代码点,每个字符都对应一个或多个二进制值。
- 不同字符集可以使用不同的编码方式,例如ASCII字符集可以使用ASCII编码,Unicode字符集可以使用UTF-8、UTF-16、UTF-32等不同的编码方式。
- 编码是字符集的物理表示,它允许计算机能够理解和处理文本数据,确保文本在存储、传输和显示时能够被正确解释。
总结:字符集(Character Set)是一个抽象概念,定义了一组字符,而编码(Encoding)是将这些字符映射到二进制数据的具体方式。字符集告诉我们哪些字符可以使用,而编码告诉计算机如何表示和处理这些字符。选择正确的字符集和编码是确保文本正确解释和显示的重要因素,尤其在多语言和国际化环境中。
1. 字符集的存储
字符集(Character Set)可以包括字母、数字、标点符号、特殊符号、控制字符等。
电脑如何进行存储文字信息:计算机通过高、低电平信号表示为1和0,用来表示2进制,进行存储,并对二进制转化为十进制表示出来——相关阅读《bit和Byte是怎么来的》(这部分对帮助理解bit和Byte很重要)
通常我们用二进制转化成十进制的方法可以表示任意数字:比如:88
0或1 <=> 01011000 <=> 二进制转化成十进制 <=> 88
如何用二进制表示其他内容呢?比如:a
1100001 <=> a
ANCII字符集 => 采用ANCII编码方法,编排了128个文字符号. 只需要7个(0或1)就可以表示完全(2^7次方),足够美国人自己使用。
ASCII编码、ANSI编码和Unicode编码的发展史
ASCII码、ANSI码和Unicode编码都是字符编码系统,它们在计算机领域的发展过程中经历了演变和扩展。它们的演变过程如下:
-
ASCII编码(American Standard Code for Information Interchange):
- 开始时间:ASCII码最早出现于上世纪60年代。由于计算机最早是美国军方和美国大学做科学研究使用的,因此ASCII码是由美国国家标准协会(ANSI)制定的。
- 字符集合:ASCII码最初定义了128个字符,包括控制字符(如回车、换行、制表符)和可显示字符(如大写字母、小写字母、数字和标点符号)。
- 编码方式:每个字符都用7位二进制数表示,因为7位二进制数(2的7次方)可以表示128个不同的字符。
- 限制:ASCII码只包含了英语字符和一些常见的特殊符号,不适用于其他语言。
- 演变:ASCII字符集最初使用7位二进制编码足够。然而,随着计算机技术的发展,人们开始寻求更多字符和符号的支持,特别是为了适应不同国家和语言的需求。为了扩展ASCII字符集以支持更多字符,通常在ASCII的基础上使用额外的位来表示字符。这就产生了扩展ASCII或8位ASCII字符集,它使用8位(1字节)来表示每个字符,从而可以表示256个不同的字符。(01111111 => 1 byte => 8bit)相关阅读——《ASCII码对照表》
-
ANSI编码(American National Standards Institute):
- ANSI码是ASCII码的一种扩展,旨在解决ASCII码的局限性。
- 字符集合:ANSI码扩展了ASCII码,提供了更多的字符,允许包括特殊符号和非英语字符在内的更多字符。
- 编码方式:ANSI码通常使用8位二进制数表示字符,因此可以表示256个不同的字符。
- 变种:不同国家和地区的ANSI码有所不同,因此存在多个ANSI码变种,如ISO 8859-1(Latin-1)用于西欧字符,ISO 8859-5 用于西里尔文字符等。(请注意到这里依旧无法表示中文,因为2的8次方65535个还不够表达所有的中国文字,并且那是70年代,计算机还没有那么普及。)
-
Unicode编码(万国码):
- 开始时间:Unicode编码的发展始于1980年代,经历了多个版本的演进。
- 字符集合:Unicode旨在包含全球所有语言的字符,它的目标是提供一个统一的字符编码系统。
- 编码方式:Unicode采用16位、32位和更多位的编码单元,以表示更多字符。最初采用16位编码,称为UTF-16,后来发展出UTF-8、UTF-32等不同的编码方案。
- 扩展:Unicode持续扩展字符集,以涵盖更多的语言和符号。它还定义了字符的规范名称和属性。
- 互通性:Unicode编码为不同平台和操作系统提供了字符互通性,允许在不同系统上正确显示各种语言的文本。
总结:ASCII码是字符编码的最早形式,用于英语字符和一些特殊符号。随后,ANSI码扩展了ASCII码,允许更多字符,但仍然有国际化限制。ANSI编码最初是为英语和一些西方语言设计的,不能支持中文字符。ANSI编码的不同变种用于支持不同国家和地区的字符,但仍然受到字符限制。最后,Unicode编码的出现解决了国际化字符集的问题,提供了全球字符的统一编码方式,确保了跨平台和跨语言的文本互通性。Unicode编码在当今的计算机系统和互联网中广泛应用。
关于各国自己研发的编码标准
在Unicode编码出现之前,各国都参照ANSI编码标准,相继开发了自己的编码标准(因为ANSI编码最初也是为英语和一些西方语言设计的):
-
日本的 JIS 编码:最早的 JIS 编码标准是 JIS X 0201,它于1969年制定。后来,JIS X 0208 和 JIS X 0213 等标准也相继制定。
-
中国的 GB 系列:GB2312 标准于1980年发布,GB2312 是中国最早的字符编码标准,用于表示简体中文字符。后来,GBK 和 GB18030 等标准分别于1995年和2000年发布,以扩展字符集和解决多字节字符表示的问题。
-
台湾的 Big5 编码:Big5 标准于1984年制定,用于表示繁体中文字符。它是台湾地区的字符编码标准。
-
俄罗斯的 KOI8 编码:KOI8 编码是基于早期的编码标准,如 KOI7 和 KOI6,于20世纪80年代制定,用于表示俄语字符。
-
希腊的 ISO 8859 编码:ISO 8859 标准系列最早于1987年发布,其中包括了用于不同欧洲语言的字符编码标准。ISO 8859-7 是用于希腊语字符的编码标准。
-
印度的 ISCII 编码:ISCII 编码标准于1988年发布,用于表示印度不同语言的字符。ISCII 包括了不同印度语言脚本的字符编码。
关于GB2312 和 GBK
GB2312 和 GBK 是中国国家标准,用于编码汉字和汉字字符集。
-
GB2312(Guo Biao 2312)是中国国家标准,最早于1980年发布,用于表示简体中文字符集。GB2312 包括了6,763个常用汉字和标点符号,使用两个字节编码。GB2312 是早期计算机系统中用于汉字处理的标准之一,它在那个时期广泛使用。
-
GBK(Guo Biao Kuozhan,国标扩展)是对 GB2312 的扩展,于1995年发布,用于支持更多汉字字符。windows 默认的中文编码GBK,包括了大约 21,000 个汉字,使用两个字节编码。GBK扩展了 GB2312 的字符集,以包括更多的汉字,特别是用于编写不同方言的汉字字符。
- GB18030:GB18030 是中国国家标准,是 GB2312 和 GBK 的扩展。它包括了更多的汉字字符,以满足多种汉字需求,包括繁体字和少数民族语言的字符。GB18030 使用四个字节(32位)来表示字符,因此它可以表示更多的字符。
- EUC-CN:EUC-CN(Extended Unix Code for Simplified Chinese)是一种用于表示简体中文的字符编码标准,通常用于Unix系统。它包括了 GB2312 字符集中的字符,使用两个字节表示。
这两种标准主要用于简化和繁体中文的字符编码。然而,需要注意的是,它们仅用于表示中文字符,不包括其他非中文字符或全球字符集。从 Unicode 编码标准的角度来看,GB2312 和 GBK 可以被看作是特定范围内的字符集,且GBK 仍然无法覆盖 Unicode 中的所有汉字字符。而 Unicode 提供了更广泛的字符表示能力,支持世界上的所有语言。因此,当需要处理多语言文本时,通常会使用 Unicode 编码方式,如 UTF-8、UTF-16 或 UTF-32,而不是 GB2312 或 GBK。
各国之间不通用的问题:
中国使用gb2312编码
01000000 01010101 => 中
日本使用JIS编码
01000000 01010101 => え
同样的内容,在发送给国际友人使用时,就出现了不同的显示乱码问题。因此国际通用的标准就慢慢的应运而生了。
Unicode(万国码): 发展史
-
Unicode 1.0(1991年):Unicode 标准的首个版本,包含7,161个字符。
-
Unicode 1.1(1993年):增加了对古代文本的支持。
-
Unicode 2.0(1996年):引入了 UTF-16 编码,增加了对汉字、希伯来字母、阿拉伯字母等的支持。
-
Unicode 3.0(1999年):扩展了字符集,包括古代文字、修饰符、货币符号等。引入了 UTF-16BE 和 UTF-16LE 编码方案。
-
Unicode 3.1(2001年):增加了对汉字的支持,包括 CJK(中文、日文、韩文)字符集的扩展,引入了 UTF-32。
-
Unicode 3.2(2002年):增加了对汉字的支持,包括日本的 JIS X 0213 字符。
-
Unicode 4.0(2003年):扩展了字符集,包括许多新的字符和符号。
-
Unicode 4.1(2005年):增加了对古代文字和修饰符的支持。
-
Unicode 5.0(2006年):增加了对表情符号(Emoji)的支持,以及其他字符和符号。
-
Unicode 5.1(2008年):增加了一些符号和修饰符。
-
Unicode 5.2(2009年):增加了一些符号和修饰符。
-
Unicode 6.0(2010年):增加了对多种新字符和符号的支持。
-
Unicode 6.1(2012年):增加了一些字符和修饰符。
-
Unicode 6.2(2012年):增加了一些符号和修饰符。
-
Unicode 6.3(2013年):增加了一些字符。
-
Unicode 7.0(2014年):扩展了字符集,包括许多新符号和字符。
-
Unicode 8.0(2015年):增加了对表情符号(Emoji)的支持,以及其他字符和符号。
-
Unicode 9.0(2016年):增加了对多种新字符、符号和文字修饰符的支持。
-
Unicode 10.0(2017年):增加了对多种新字符和表情符号的支持。
-
Unicode 10.1(2017年):增加了一些字符和修饰符。
-
Unicode 11.0(2018年):扩展了字符集,包括新的字符、表情符号、货币符号等。
-
Unicode 12.0(2019年):增加了对许多新字符和符号的支持。
-
Unicode 12.1(2019年):增加了一些字符和修饰符。
-
Unicode 13.0(2020年):扩展了字符集,包括表情符号、数学符号等。
-
Unicode 13.1(2020年):增加了一些字符和修饰符。
-
Unicode 14.0(2021年):增加了对多种新字符和表情符号的支持。
通用字符集(Universal Character Set, UCS)是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的标准字符集。UCS-2用两个字节编码,UCS-4用4个字节编码。
早期Unicode没有意识到把所有文字容纳到一起的庞大数量问题,使用的是UCS-2,最大是2个字节。后来进行了扩充, UCS-4,最大使用4个字节
#早期的ASCII编码,每个字符 7bit => 128
1010101
#ASCII编码,每个字符 8bit => 1byte => 256
10101010
#ANSI编码,每个字符 16bit => 2byte => 65536
00000000 01111111
#Unicode编码,UCS-2标准,每个字符 16bit => 2byte => 65536
00000000 01111111
#Unicode编码,UCS-4标准,每个字符 32bit => 4byte => 4294967296
00000000 00000000 00000000 01111111
但是单纯的把协议扩大,就出现了严重占用磁盘空间,和传输带宽利用率问题。
如果你的文本内容中仅仅是纯英文,那么8位的ANSI编码长度的就足够使用了,但是你要是有中文等,却不够表示。
于是科学家们研究出了可变长度的Unicode——UTF
UTF: 是可变长度的Unicode,可以进行数据的传输和存储 -> 行书, 草书, 隶书
UTF-8: 最短的字节长度8(英文),通过对不同的内容标定不同的字节占用长度,来达到最小化占用和传输的目的。
- 英文: 8bit, 1byte => 256
- 欧洲文字: 16bit, 2byte => 65536
- 中文: 24bit, 3byte => 16777216
UTF-16:
- 大多数字符使用一个16位的编码单元(2字节)表示。
- 辅助字符采用一对16位编码单元(共4字节)来表示。这一对编码单元包括一个高位编码单元(High Surrogate)和一个低位编码单元(Low Surrogate)。
UTF-32:
- UTF-32是一种固定长度的编码方案,每个字符始终都占用32位(4个字节)。
如果你需要在计算机中表示和处理中文字符,通常会使用Unicode编码,如UTF-8、UTF-16或UTF-32,以支持包括汉字在内的所有字符。这些Unicode编码是为全球性的字符支持而设计的,可用于表示多种语言,包括中文。UTF-8是一种常见的Unicode编码方式,它使用可变长度的编码单元来表示字符,能够有效减小计算机存储的空间浪费问题。Unicode编码能够有效地表示中文字符和其他非拉丁字符。如果要在计算机系统中处理中文文本,建议使用UTF-8编码。
UTF-8、UTF-16和UTF-32都提供了足够的编码空间来表示相同的字符集,因此它们都能够表示相同数量的中文汉字以及其他Unicode字符。不同的编码方式只是以不同的方式表示相同的字符,具有相同的字符表示能力,不会导致字符数量的差异。UTF-16每个字符可以占用16位(2个字节)或32位(4个字节),而UTF-32使用一个32位编码单元表示字符。这意味着对于每个字符,它们的编码长度是固定的。
总结:
1. ASCII编码: 8bit, 1byte => 256
2. GBK编码: Windows系统默认 16bit, 2byte => 65536
3. Unicode编码:32bit => 4byte => 4294967296(因为浪费,没法用, 只是一个标准)
4. UTF-8编码: MAC系统默认
- 英文: 8bit, 1byte => 256
- 欧洲文字: 16bit, 2byte => 65536
- 中文: 24bit, 3byte => 16777216
5.GBK编码存储汉字(2byte)比UTF-8编码存储汉字(3byte)节省空间
6.GBK编码和UTF-8编码不能直接就进行转化。因为是2套标准,我军密码本(GBK) <-> 转文字 <-> 敌军密码本(UTF-8)
扩展阅读:UTF16及GB18030编码介绍
汉字在Unicode中的分布
在Unicode中,中日韩的汉字集中在几个区域,但是它们之间是混在一起的。这几个区域分别是:
块名称 | 位置 | 汉字个数 | 描述 |
CJK Unified Ideographs | 4E00–9FFF | 20,991 | 常用字 |
CJK Unified Ideographs Extension A | 3400–4DBF | 6591 | 生僻字 |
CJK Unified Ideographs Extension B | 20000–2A6DF | 42,719 | 古汉字遗留的生僻字 |
CJK Unified Ideographs Extension C | 2A700–2B73F | 4,159 | 古汉字遗留的生僻字 |
CJK Unified Ideographs Extension D | 2B740–2B81F | 223 | 现在还在用,但使用较少 |
CJK Unified Ideographs Extension E | 2B820–2CEAF | 5,775 | 古汉字遗留的生僻字 |
CJK Compatibility Ideographs | F900–FAFF | 511 | 重复的变体字 |
CJK Compatibility Ideographs Supplement | 2F800–2FA1F | 543 | 变体字 |
总计 | 81,432 |
备注:查到的不同资料,汉字分布区间的字数不太一致,待确认。下面链接的分布表可作参考。
Unicode编码分布表: http://chineselanguageformula.sourceforge.net/traditional/unicode-planes.html
Unicode 5.0中,如果不算兼容区,目前有70217个汉字。让我们比较一下Unicode的70217汉字和GB18030-2005中的70244汉字:
GB18030-2005 | Unicode 5.0 | 对应的Unicode编码 |
CJK统一汉字的20902汉字 | CJK统一汉字的20902汉字 | 0x4E00-0x9FA5 |
CJK统一汉字扩充A的6582汉字 | CJK统一汉字扩充A的6582汉字 | 0x3400-0x4DB5 |
CJK统一汉字扩充B的42711汉字 | CJK统一汉字扩充B的42711汉字 | 0x20000-0x2A6D6 |
CJK部首补充区的14个部首 | 未计入 | 2E81, 2E84, 2E88, 2E8B, 2E8C, 2E97, 2EA7, 2EAA, 2EAE, 2EB3, 2EB6, 2EB7, 2EBB, 2ECA |
CJK兼容汉字区的21个汉字 | 未计入 | F92C, F979, F995, F9E7, F9F1, FA0C, FA0D, FA0E, FA0F, FA11, FA13, FA14, FA18, FA1F, FA20, FA21, FA23, FA24, FA27, FA28, FA29 |
8个部首 | CJK统一汉字区新增了这8个字符 | 0x9FB4-0x9FBB |
未计入 | CJK统一汉字区新增的14个字符 | 0x9FA6-0x9FB3 |
8个部首:
CJK统一汉字区新增的0x9FA6-0x9FB3这14个字符在GB18030中有对应的码位(0x82358F33-0x82358F39, 0x82359030-0x82359039, 0x82359130-0x82359134),不过GB18030没有列出这些字符。