character coding
跟随历史的足迹看字符编码
古代的通信方式
很久很久以前, 人们之间的长途通讯主要是用信鸽骑马送报烽烟等方式进行
直到 1837 年, 世界第一条电报诞生, 当时美国科学家莫尔斯尝试用一些点和划来表示不同的字母数字和标点符号, 这套表示字符的方式也被称为摩尔斯电码
世界第一台计算机
再后来到了 1946 年, 世界第一台计算机诞生发明计算机的同学们用 8 个晶体管的通或断组合出一些状态来表示世间万物, 不过当时的计算机有一间半教室那么大, 六头大象重, 从现在看来这简直就是个怪物, 但在当时却是震惊世界与改变世界的一项重要发明
ASCII (American Standard Code for Information Interchange)
8 个晶体管的通或断即可以代表一个字节, 刚开始, 计算机只在美国使用, 所有的信息在计算机最底层都是以二进制 (0 或 1 两种不同的状态) 的方式存储, 而 8 位的字节一共可以组合出 256(2 的 8 次方)种状态, 即 256 个字符, 这对于当时的美国已经是足够的了, 他们尝试把一些终端的动作字母数字和符号用 8 位 (bit) 来组合
128 个码位, 用 7 位二进制数表示, 由于计算机 1 个字节是 8 位二进制数, 所以最高位为 0, 即 00000000-01111111 或 0x00-0x7F
比特(bit): 也可称为位, 是计算机信息中的最小单位, 是 binary digit(二进制数位) 的 缩写, 指二进制中的一位
字节 (Byte): 计算机中信息计量的一种单位, 一个位就代表 0 或 1, 每 8 个位(bit) 组成一个字节(Byte)
字符(Character): 文字与符号的总称, 可以是各个国家的文字标点符号图形符号数字等
字符集(Character Set): 是多个字符的集合
编码(Encoding): 信息从一种形式或格式转换为另一种形式的过程
解码(decoding): 编码的逆过程
字符编码(Character Encoding): 按照何种规则存储字符
现在我们来看我们文章开头提到的第一条电报的诞生, 莫尔斯编码中包含了大小写英文字母和数字等符号
这里的每一个符号其实就是? 字符?,
而这所有的字符的集合就叫做? 字符集?,
点或划与字符之间的对应关系即可以称为? 字符编码?
而电报的原理是:
点对应于短的电脉冲信号, 划对应于长的电脉冲信号, 这些信号传到对方, 接收机把短的电脉冲信号翻译成点, 把长的电脉冲信号转换成划, 译码员根据这些点划组合就可以译成英文字母, 从而完成了通信任务
这里把字符表示为点或划并对应为电脉冲信号的过程既是? 编码?,
而译码员把接收机接收到的脉冲信号转化成点划后译成字符的过程即为? 解码?
而对于计算机诞生之后, 只不过是将摩斯电码中的点和划换成了以 8 位字节二进制流的方式表示, 如数字 1 的二进制流是 0011 0001, 对应的十进制流是 49, 十六进制流是 31
奇偶校验
简单来说, 奇偶校验是一种检测数据传输时正确性的方法, 它分为 奇校验 和 偶校验两种, 分别检测二进制数据中 1 的个数是奇数或偶数 并将校验结果位追加到数据之后
奇校验:
如果数据中的 1 的个数是奇数, 那么校验位为 0 否则为 1
例如: 1001000 => 奇校验 1001000+1 , 1001001 => 奇校验 1001001+0
偶校验:
如果数据中的 1 的个数是偶数, 那么校验位为 0 否则为 1
例如: 1001000 => 偶校验 1001000+0 , 1001101 => 偶校验 1001101+1
奇偶校验只能检查错误, 但并不能纠正错误
单字节编码
EASCII (Extended ASCII)
虽然刚开始计算机只在美国使用, 128 个字符的确是足够了, 但随着科技惊人的发展, 欧洲国家也开始使用上计算机了不过 128 个字符明显不够呀, 比如法语中, 字母上方有注音符号, 于是, 一些欧洲国家就决定, 利用字节中闲置的最高位编入新的符号
比如, 法语的 é 的二进制流为 1000 0010, 这样一来, 这些欧洲国家的编码体系, 可以表示最多 256 个字符了 但是, 这里又出现了新的问题不同的国家有不同的字母, 因此, 哪怕它们都使用 256 个符号的编码方式, 代表的字母却不一样比如, 1000 0010 在法语编码中代表了 é, 在希伯来语编码中却代表了字母 Gimel (?), 在俄语编码中又会代表另一个符号但是不管怎样, 所有这些编码方式中, 0--127 表示的符号是一样的, 不一样的只是 128--255 的这一段 EASCII(Extended ASCII, 延伸美国标准信息交换码)由此应运而生, EASCII 码比 ASCII 码扩充出来的符号包括表格符号计算符号希腊字母和特殊的拉丁符号:
256 个码位, 用 8 位二进制数表示, 即 00000000-11111111 或 0x00-0xFF
ISO-8859 (国际化标准组织 - 8859)
ISO-8859 全称 ISO/IEC 8859, 是国际标准化组织 (ISO) 及国际电工委员会 (IEC) 联合制定的一系列 8 位字符集的标准, 现时定义了 15 个字符集
ASCII 收录了空格及 94 个可印刷字符, 足以给英语使用但是, 其他使用拉丁字母的语言(主要是欧洲国家的语言), 都有一定数量的附加符号字母, 故可以使用 ASCII 及控制字符以外的区域来储存及表示
除了使用拉丁字母的语言外, 使用西里尔字母的东欧语言希腊语泰语现代阿拉伯语希伯来语等, 都可以使用这个形式来储存及表示
按国家 / 地区分别编码 ISO 陆续语系)的扩充 ASCII 制定了十多个适用于不同国家和地区(均为拉丁字符集(高位为 1 的 8 位代码), 称为 ISO8859
又称为 扩充 ASCII 字符集
ISO/IEC 8859-1 (Latin-1) - 西欧语言
ISO/IEC 8859-2 (Latin-2) - 中欧语言
ISO/IEC 8859-3 (Latin-3) - 南欧语言世界语也可用此字符集显示
ISO/IEC 8859-4 (Latin-4) - 北欧语言
ISO/IEC 8859-5 (Cyrillic) - 斯拉夫语言
ISO/IEC 8859-6 (Arabic) - 阿拉伯语
ISO/IEC 8859-7 (Greek) - 希腊语
ISO/IEC 8859-8 (Hebrew) - 希伯来语(视觉顺序)
ISO 8859-8-I - 希伯来语(逻辑顺序)
ISO/IEC 8859-9(Latin-5 或 Turkish)- 它把 Latin-1 的冰岛语字母换走, 加入土耳其语字母
ISO/IEC 8859-10(Latin-6 或 Nordic)- 北日耳曼语支, 用来代替 Latin-4
ISO/IEC 8859-11 (Thai) - 泰语, 从泰国的 TIS620 标准字集演化而来
ISO/IEC 8859-13(Latin-7 或 Baltic Rim)- 波罗的语族
ISO/IEC 8859-14(Latin-8 或 Celtic)- 凯尔特语族
ISO/IEC 8859-15 (Latin-9) - 西欧语言, 加入 Latin-1 欠缺的芬兰语字母和大写法语重音字母, 以及欧元 () 符号
ISO/IEC 8859-16 (Latin-10) - 东南欧语言主要供罗马尼亚语使用, 并加入欧元符号
由于英语没有任何重音字母(不计外来词), 故可使用以上十五个字集中的任何一个来表示
至于德语方面, 因它除了 A-Z, a-z 外, 只用 ?, ?, ü, ?, ?, ?, ü 七个字母, 而所有拉丁字集 (1-4, 9-10, 13-16) 均有此七个字母, 故德语可使用以上十个字集中的任何一个来表示
此系列中没有 - 12 号的原因是, 此计划原本要设计成一个包含塞尔特语族字符集的 Latin-7, 但后来塞尔特语族变成了 ISO 8859-14 / Latin-8 亦有一说谓 - 12 号本来是预留给印度天城体梵文的, 但后来却搁置了
这套编码规则由 ISO 组织制定是在 ASCII 码基础上又制定了一些标准用来扩展 ASCII 编码, 即 00000000(0) ~ 01111111(127) 与 ASCII 的编码一样, 对 10000000(128) ~ 11111111(255)这一段进行了编码, 如将字符 § 编码成 10100111(167)ISO-8859-1 编码也是单字节编码, 最多能够表示 256 个字符 Latin1 是 ISO-8859-1 的别名, 有些环境下写作 Latin-1 但是, 即使能够表示 256 个字符, 对中文而言, 还是太少了, 一个字节肯定不够, 必须用多个字节表示但是, 由于是单字节编码, 和计算机最基础的表示单位一致, 所以很多时候, 仍旧使用 ISO8859-1 编码来表示而且在很多协议上, 默认使用该编码比如, 虽然 "中文" 两个字不存在 ISO8859-1 编码, 以 GB2312 编码为例, 应该是 D6D0 CEC4 两个字符, 使用 ISO8859-1 编码的时候则将它拆开为 4 个字节来表示: D6D0 CEC4(事实上, 在进行存储的时候, 也是以字节为单位进行处理)而如果是 UTF 编码, 则是 6 个字节 e4 b8 ad e6 96 87 很明显, 这种表示方法还需要以另一种编码为基础才能正确显示而常见的中文编码方式有 GB2312BIG5GBK
多字节编码
GB2312
EASCII 码对于部分欧洲国家基本够用了, 但过后的不久, 计算机便来到了中国, 要知道汉字是世界上包含符号最多并且也是最难学的文字 据不完全统计, 汉字共包含了古文现代文字等近 10 万个文字, 就是我们现在日常用的汉字也有几千个, 那么对于只包含 256 个字符的 EASCII 码也难以满足天朝的需求了 于是? 中国国家标准总局?(现已更名为? 国家标准化管理委员会?)在 1981 年, 正式制订了中华人民共和国国家标准简体中文字符集, 全称信息交换用汉字编码字符集. 基本集, 项目代号为 GB 2312 或 GB 2312-80(GB 为国标汉语拼音的首字母), 此套字符集于当年的 5 月 1 日起正式实施
GB2312 是最早 (1980 年) 发布的中国国家标准字符集 , 是一个典型的双字节字符集(DBCS) 他规定了两个连续大于 127 的字节代表一个汉字, 否则就当做 ASCII 来处理, 这样的两字节中高位字节范围 0xA1-0xF7, 低位字节范围 0xA1-0xFE 二者相乘多出来 8000 多个坑位, 已经足够容纳常用汉字了, 除此之外还增加了数学符号罗马希腊字母日文假名等 这种规则完全兼容 ASCII , 但为了更好的兼容 CP437 也做了很多空间牺牲, 比如 GB2312 的低位也被要求大于 127, 所以 GB2312 的编码空间并不大
包含字符:
1981 年 5 月 1 日发布的简体中文汉字编码国家标准 GB2312 对汉字采用双字节编码, 收录 7445 个图形字符, 其中包括 6763 个汉字, 682 个其他字符(拉丁字母希腊字母日文平假名及片假名字母俄语西里尔字母)
存储方式:
基于 EUC 存储方式, 每个汉字及符号以两个字节来表示, 第一个字节为高位字节, 第二个字节为低位字节
GB2312 其对所收录字符进行了 "分区" 处理, 共 94 个区, 区从 1(十进制)开始, 一直到 94(十进制), 每区含有 94 个位, 位从 1(十进制)开始, 一直到 94(十进制), 共 8836(94 * 94)个码位, 这种表示方式也称为区位码, GB2312 是双字节编码, 其中高字节表示区, 低字节表示位各区具体说明如下:
01-09 区收录除汉字外的 682 个字符, 有 164 个空位(9 * 94 - 682)
10-15 区为空白区, 没有使用
16-55 区收录 3755 个一级汉字(简体), 按拼音排序
56-87 区收录 3008 个二级汉字(简体), 按部首 / 笔画排序
88-94 区为空白区, 没有使用
那么根据区位码如何算出 GBK2312 编码呢? 区位码的表示范围为 0101 - 9494(包含了空的区位码)查看中 GB2312 编码区位码之后只需要按照如下规则进行转化即可
将区 (十进制) 转化为十六进制
将转化的十六进制加上 A0, 得到 GB2312 编码的高字节
将位 (十进制) 转化为十六进制
将转化的十六进制加上 A0, 得到 GB2312 编码的低字节
组合区和位, 区在高字节, 位在低字节
得到 GB2312 编码
例如: 李字的区位码为 3278(表示在 32 区, 78 位)
将 32(区)转化为十六进制为 20
加上 A0 为 C03. 将 78(位)转化为十六进制为 4E
加上 A0 为 EE
组合区和位, 为 C0EE
得到 GB2312 编码, 即李字的 GB2312 编码为 C0EE
GB2312 用两个字节编码, 采用分区编码, 总共编码的中文个数为 6763(3755 + 3008)这些汉字只是最常用的汉字, 已经覆盖中国大陆 99.75% 的使用频率但是, 还有一些汉字在 GB2312 中没有被编码, 如镕字, 在 GB2312 中就没有被编码, 这样就导致了问题, 随之就出现了主流的 GBK 编码在讲解 GBK 编码之前, 我们另外讲解一下 BIG5 编码
早期的计算机运算能力非常弱, 而 GB2312 的编码规则无形中又给解码增加了额外负担, 所以为了提高汉字的输入性能, 一种叫 汉卡 的硬件出现了, 他直接负责 GB2312 的编码解码 为 CPU 分担任务
但作为一款硬件, 它的流行又使得 GB13000 推行不下去
BIG5
要知道港澳台同胞使用的是繁体字, 而中国大陆制定的 GB2312 编码并不包含繁体字, 于是信息工业策进会在 1984 年与台湾 13 家厂商签定 16 位个人电脑套装软件合作开发 (BIG-5) 计划, 并开始编写并推出 BIG5 标准 之后推出的倚天中文系统则基于 BIG5 码, 并在台湾地区取得了巨大的成功在 BIG5 诞生后, 大部分的电脑软件都使用了 Big5 码, BIG5 对于以台湾为核心的亚洲繁体汉字圈产生了久远的影响, 以至于后来的 window 繁体中文版系统在台湾地区也基于 BIG5 码进行开发
包含字符:
共收录 13,060 个汉字及 441 个符号
编码方式:
用两个字节来为每个字符编码, 第一个字节称为高位字节, 第二个字节称为低位字节
BIG5 采用双字节编码, 使用两个字节来表示一个字符高位字节使用了 0x81-0xFE, 低位字节使用了 0x40-0x7E, 及 0xA1-0xFE 该编码是繁体中文字符集编码标准, 共收录 13060 个中文字, 其中有二字为重复编码, 即兀兀 (A461 及 C94A) 和嗀嗀 (DCD1 及 DDFC) 具体的分区如下:
8140-A0FE 保留给使用者自定义字符(造字区)
A140-A3BF 标点符号希腊字母及特殊符号其中在 A259-A261, 收录了度量衡单位用字: 兙兛兞兝兡兣嗧瓩糎
A3C0-A3FE 保留此区没有开放作造字区用
A440-C67E 常用汉字, 先按笔划再按部首排序
C6A1-F9DC 其它汉字
F9DD-F9FE 制表符
Unicode
在计算机进入中国大陆的相同时期, 计算机也迅速发展进入了世界各个国家 特别是对于亚洲国家而言, 每个国家都有自己的文字, 于是每个国家或地区都像中国大陆这样去制定了自己的编码标准, 以便能在计算机上正确显示自己国家的符号 但带来的结果就是国家之间谁也不懂别人的编码, 谁也不支持别人的编码, 连大陆和台湾这样只相隔了 150 海里, 都使用了不同的编码体系 于是, 世界相关组织意识到了这个问题, 并开始尝试制定统一的编码标准, 以便能够收纳世界所有国家的文字符号 在前期有两个尝试这一工作的组织:
国际标准化组织(ISO)
国际标准化组织 (ISO) 及国际电工委员会 (IEC) 于 1984 年联合成立了 ISO/IEC 小组, 主要用于开发统一编码项目
统一码联盟
而 XeroxApple 等软件制造商则于 1988 年组成了统一码联盟, 用于开发统一码项目
两个组织都在编写统一字符集, 但后来他们发现各自在做相同的工作, 同时世界上也不需要两个不兼容的字符集, 于是两个组织就此合并了双方的工作成果, 并为创立一个单一编码表而协同工作
1991 年, 年, 两个组织共同的工作成果 Unicode 1.0 正式发布, 不过 Unicode 1.0 并不包含 CJK 字符(即中日韩)
Unicode 1.0:1991 年 10 月
Unicode 1.0.1:1992 年 6 月
Unicode 1.1:1993 年 6 月
Unicode 2.0:1997 年 7 月
Unicode 2.1:1998 年 5 月
Unicode 2.1.2:1998 年 5 月
Unicode 3.0:1999 年 9 月
Unicode 3.1:2001 年 3 月
Unicode 3.2:2002 年 3 月
Unicode 4.0:2003 年 4 月
Unicode 4.0.1:2004 年 3 月
Unicode 4.1:2005 年 3 月
Unicode 5.0:2006 年 7 月
Unicode 5.1:2008 年 4 月
Unicode 5.2:2009 年 10 月
Unicode 6.0:2010 年 10 月
Unicode 4.1:2005 年 3 月
Unicode 6.1:2012 年 1 月 31 日
Unicode 6.2:2012 年 9 月
ISO/IEC 8859
ISO/IEC 小组在 1984 年成立后的第三年 (即 1987 年) 开始启动 ISO 8859 标准的编写, ISO 8859 是一系列 8 位字符集的标准, 主要为世界各地的不同语言 (除 CJK) 而单独编写的字符集, 一共定义了 15 个字符集
其中 ISO/IEC 8859-1 至 ISO/IEC 8859-4 四个项目早在 1982 年就已经编写出来, 只不过是由 ANSI 与 ECMA 合作完成, 并于 1985 年正式公布, ISO/IEC 小组成立后, 这一成果被其收录, 并改名为 ISO/IEC 8859 前四个项目 大家其实发现以上 15 个字符集中并没有代号为 ISO/IEC 8859 -12 的字符集, 据说 - 12 号本来是预留给印度天城体梵文的, 但后来却搁置了 (阿三有了自己的编码 - ISCII) 由于英语没有任何重音字母, 故可使用以上十五个字符集中的任何一个来表示
ISO/IEC 10646 / UCS
1993 年, ISO/IEC 10646 标准第一次发表, ISO/IEC 10646 是 ISO 646 的扩展, 定义了 1 个 31 位的字符集 ISO 10646 标准中定义的字符集为 UCS,UCS 是 Universal Character Set 的缩写, 中文译作通用字符集
版本
ISO/IEC 10646-1: 第一次发表于 1993 年, 现在的公开版本是 2000 年发表的 ISO/IEC 10646-1:2000
ISO/IEC 10646-2: 在 2001 年发表
包含字符:
最初的 ISO 10646-1:1993 的编码标准, 即 Unicode 1.1, 收录中国大陆台湾日本及韩国通用字符集的汉字共计 20,902 个, 当然每个版本的 Unicode 标准的字符集所包含的字符数不尽相同, UCS 包含了已知语言的所有字符, 除了拉丁语希腊语斯拉夫语希伯来语阿拉伯语亚美尼亚语格鲁吉亚语, 还包括中文日文韩文这样的方块文字, 此外还包括了大量的图形印刷数学科学符号 UCS 给每个字符分配一个唯一的代码, 并且赋予了一个正式的名字, 通常在表示一个 Unicode 值的十六进制数的前面加上 U+, 例如 U+0041 代表字符 A
编码方案:
UCS 仅仅是一个超大的字符集, 关于 UCS 制定的编码方案有两种: UCS-2 和 UCS-4,Unicode 默认以 UCS-2 编码 顾名思义, UCS-2 就是用两个字节编码, UCS-4 就是用 4 个字节 (实际上只用了 31 位, 最高位必须为 0) 编码那么 UCS-2 其实可以容纳的字符数为 65536(2 的 16 次方), 而 UCS-4 可以容纳的字符数为 2147483648(2 的 31 次方)其实对于 UCS-2 已经是完全够用了, 基本可以包含世界所有国家的常用文字, 如果需要考虑一些偏僻字, 那么 UCS-4 则绝对可以满足了, 21 亿个字符哪怕是整个宇宙也够用了吧!
UTF
Unicode 诞生, 随之而来的计算机网络也发展了起来, Unicode 如何在网络上传输也是一个必须考虑的问题, 于是在 1992 年, 面向网络传输的 UTF 标准出现了 UTF 是 Unicode Transformation Format 的缩写, 中文译作 Unicode 转换格式其实我们从现在可以把 Unicode 看作是一个标准或组织, 而 UCS 就是一个字符集, 那么 UCS 在网络中的传输标准就是 UTF 了 前面提到了 UCS 的编码实现方式为 UCS-2 和 UCS-4, 即要么是每个字符为 2 个字节, 要么是 4 个字节如果一个仅包含基本 7 位 ASCII 字符的 Unicode 文件, 每个字符都使用 2 字节的原 Unicode 编码传输, 其第一字节的 8 位始终为 0, 这就造成了比较大的浪费但是, 聪明的人们发明了 UTF-8,UTF-8 采用可变字节编码, 这样可以大大节省带宽, 并增加网络传输效率
UTF-8
虽然 unicode 帮我们解决了字符集统一的问题, 但这并不是没代价的 在 unicode 下所有的字符都是用 2(UCS2) 或 4(UCS4) 个字节来编码, 甚至是 ASCII 字符 这样便造成了大量浪费, 尤其是在进行网络传输的时候 (当你走进联通营业厅后会发现, 流量啊 流量 你可是真金白银啊)
为了解决这一问题, 科学家们定义了一种基于 unicode 的便于传输的编码格式 UTF(UCS Transfer Format), UTF 也有 UTF-8 UTF-16 UTF-32 这几个兄弟 横杠后的数字代表尝试将单个 unicode 压缩成几 bit
比如 UTF-8 它就将尝试用 8 bit 来表示一个 unicode 字
十六进制 二进制
- 0000 0000-0000 007F 0xxxxxxx
- 0000 0080-0000 07FF 110xxxxx 10xxxxxx
- 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
- 0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
如果某字节第一位是 0 , 那么判定为 ASCII 字节, 除了 0 外余下的 7 位是 ASCII 码所以 UTF-8 是兼容 ASCII 码的
如果第一个字节是 1 , 那么连续的几个 1 代表了从这个字符开始, 后面连续的几个字符其实是一个字位 且后面的位置都要是用 10 开头的
使用 1~4 个字节为每个 UCS 中的字符编码:
128 个 ASCII 字符只需一个字节编码(Unicode 范围由 U+0000 至 U+007F)
拉丁文希腊文西里尔字母亚美尼亚语希伯来文阿拉伯文叙利亚文及它拿字母需要二个字节编码(Unicode 范围由 U+0080 至 U+07FF)
大部分国家的常用字 (包括中文) 使用三个字节编码
其他极少使用的生僻字符使用四字节编码
UTF-16/UCS-2
UCS-2 的父集, 使用 2 个或 4 个字节来为每个 UCS 中的字符编码:
128 个 ASCII 字符需两个字节编码
其他字符使用四个字节编码
UTF-32/UCS-4
等同于 UCS-4, 对于所有字符都使用四个字节来编码
GB13000
前面提到了 Unicode 的迅速发展, 至 1993 年时, 包含 CJK 的 Unicode 1.1 已经发布了, 天朝的 ZF 也意识到了需要一个更大的字符集来走向世界, 于是在同一年, 中国大陆制定了几乎等同于 Unicode1.1 的 GB13000.1-93 国家编码标准 (简称 GB13000) 中华人民共和国信息产业部把 Unicode 重新修订发布了下, 改为了国家标准 GB13000 此标准等同于 ISO/IEC 10646.1:1993 和 Unicode 1.1
GBK
鉴于我国汉卡的流行情况, 我国有关部门又制定了 GBK 标准, 它兼容 GB2312, 同时又新增了 2w 多个坑位
它是怎么做到的呢?
GBK 放开了一些范围, 相比 GB2312 , GBK 的高位字节扩展到了 0×81-0xFE, 低位字节扩展到了 0x40-0xFE (不包含 0x7F) 编码方式和 GB2312 相同
由此可见 GBK 是 GB2312 的一个超集, 且和子集兼容良好
1995 年, 在 GB13000 诞生后不久, 中国教育科研网 (NCFC) 与美国 NCFnet 直接联网, 这一天是中国被国际承认为开始有网际网路的时间此后网络正式开始在中国大陆接通, 个人计算机开始在中国流行, 虽然当时只是高富帅才消费得起的产品中国是一个十几亿人口的大国, 微软意识到了中国是一个巨大的市场, 当时的微软也将自己的操作系统市场布局进中国, 进入中国随之而来要解决的就是系统的编码兼容问题 之前的国家编码标准 GB2312, 基本满足了汉字的计算机处理需要, 它所收录的汉字已经覆盖中国大陆 99.75% 的使用频率但对于人名古汉语等方面出现的罕用字和繁体字, GB2312 不能处理, 因此微软利用了 GB2312 中未使用的编码空间, 收录了 GB13000 中的所有字符制定了汉字内码扩展规范 GBK(K 为汉语拼音 Kuo Zhan 中扩字的首字母)所以这一关系其实是大陆把 Unicode1.1 借鉴过来改名为了 GB13000, 而微软则利用 GB2312 中未使用的编码空间收录 GB13000 制定了 GBK 所以 GBK 是向下完全兼容 GB2312 的
包含字符:
共收录 21886 个字符, 其中汉字 21003 个, 字符 883 个
编码方式:
GBK 只不过是把 GB2312 中未使用的空间, 编码了其他字符, 所以 GBK 同样是用两个字节为每个字符进行编码
GB18030
微软到了 99 年前后, 说 GBK 已经落伍了, 现在流行 UTF-8 标准, 准备全盘转换成 UTF-8GB18030 的诞生还有一个原因是 GBK 只包含了大部分的汉字和繁体字等, 我们的少数民族兄弟根本木有考虑! 中国有 56 个民族, 其中有 12 个民族有自己的文字, 那怎么办呢? 在 2000 年, 电子工业标准化研究所起草了 GB18030 标准, 项目代号 GB 18030-2000, 全称信息技术 - 信息交换用汉字编码字符集 - 基本集的扩充此标准推出后, 在中国大陆之后的所售产品必须强制支持 GB18030 标准.
GB18030 是目前我国最新的内码字集, 它和其他 GB 开头的小伙伴最大的区别就是, 它是变长的编码集
所谓变长是指一个 GB18030 字有可能由 1 个 2 个或 4 个字节组成 与 UTF 系列类似
它与 GBK , GB2312 , ASCII 都是兼容的
1 字节的值范围: 0 到 0x7F, 与 ASCII 兼容
2 字节的值范围: 高位 0x81 到 0xFE 低位 0x40 到 0xFE 与 GBK 标准兼容
4 字节的值范围: 一字节 0x81 到 0xFE, 二字节 0x30 到 0x39, 三字节 0x81 到 0xFE, 四字节从 0x30 到 0x39
GB18030 可容纳的编码范围巨大, 基本上亚洲所有的少数民族的文字都包含在内了
可以看出在这 GB 几兄弟中 GB2312 => GBK => GB18030 被依次兼容
包含字符:
GB18030 收录了 GBK 中的所有字符, 并将 Unicode 中其他中文字符 (少数民族文字偏僻字) 也一并收录进来重新编码其中 GB 18030-2000 共收录 27533 个汉字, 而 GB 18030-2005 共包含 70244 个汉字
编码方式:
采用多字节编码, 每个字符由 1 或 2 或 4 个字节进行编码
BOM (byte-order mark)
为 Unicode 标准为了用来区分一个文件是 UTF-8 还是 UTF-16 或 UTF-32 编码方式的记号, 又称字节序
UTF-8 以单字节为编码单元, 并没有字节序的问题, 而 UTF-16 以两个字节为编码单元, 在解释一个 UTF-16 文本前, 首先要弄清楚每个编码单元的字节序例如奎的 Unicode 编码是 594E, 乙的 Unicode 编码是 4E59 如果我们收到 UTF-16 字节流 594E, 那么这是奎还是乙? 这是 UTF-16 文件开头的 BOM 就有作用了
采用 Unicode 编码方式的文件如果开头出现了 FEFF,FEFF 在 UCS 中是不存在的字符, 也叫做 ZERO WIDTH NO-BREAK SPACE, 那么就表明这个文件的字节流是 Big-Endian(高字节在前)的; 如果收到 FFFE, 就表明字节流是 Little-Endian(低字节在前)
在 UTF-8 文件中放置 BOM 主要是微软的习惯, BOM 其实是为 UTF-16 和 UTF-32 准备的, 微软在 UTF-8 使用 BOM 是因为这样可以把 UTF-8 和 ASCII 等编码明确区分开, 但这样的文件在 Window 以外的其他操作系统里会带来问题
来源: http://www.bubuko.com/infodetail-2515188.html