编码发展历史

第一阶段 ASCII

在计算机中,所有的数据只可能是0或者1(用高电平和低电平分别表示1和0),那么我们通常看到的字符也就只能用0和1来表示呀。于是科学家们(这里指的是美国的科学家)就想出一个办法,把一个特定的数字对应一个特定的字母进行存储和传输,比如我需要存储字母a,那么我存入一个数字97(即在计算机中存入二进制(01100001),这个过程叫做编码(encode),而我们在读取数据的时候,当遇到97时,我们就让计算机显示字母a,这个过程叫做解码(decode)。
为了大家在数据传输的时候不至于产生误会,那么我们需要让所有的人都使用数字97来代表字母a,所以需要制定一份标准(即码表),最开始的这个标准叫做ASCII码表。
规则

  • 所有的控制字符(比如CR回车、DEL删除等)编码在0-31范围以及127中。
  • 把所有的标点符号,英文大小写全部放在32-126范围中。
  • 防止以后出现需要补充的情况,把128-255位这么多位置留出来,应该足够用了吧!所以设置一个字节8位二进制,把这个标准叫American Standard Code for Information Interchange(美国标准信息交换代码,简写为ASCII),标准制定结束。

等等,我们的中文字呢?
美国的"砖家"没有考虑那么久远呢!这就是后面出现那么多问题的根源所在啊。
实现方式
第一位始终未0,后面7位表示0-127的范围,一个数字对应一个字母或者标点符号,亦或者控制符号,即所有的ASCII码的统一形式为0xxxx xxxx。

第二阶段 GB2312,GBK, BIG5 Latin1, ISO-8859-1, JIS, ANSI...

计算机技术到了欧洲,欧洲人发现怎么我们的那么多符号没有编进去啊!
所以欧洲"砖家"坐到了一起,开始讨论。
发现既然美国人把第一位流出来了,那么我们就用128-255的位置好了。
规则
128-159之间为控制字符,160-255位文字符号,其中包括了西欧语言、希腊语、泰语、阿拉伯语、希伯来语。
刚好把美国人给的空间全部用完,世界真美好,谢谢美利坚预留的每一个位置。
砖家们决定把他们的编码名称叫做Latin1,后面由于欧洲统一制定ISO标准,所以又有了一个ISO的名称,即ISO-8859-1。
实现方式

  • 0-127的所有位置不动,那么可以兼容ASCII,二进制位0xxx xxxx
  • 128-255位置全部用完,二进制位1xxx xxxx
    由于所有的位置全部用完,而欧元符号实在指定标准之后才出现的,所以在这个码表中连欧洲人自己的货币符号都没有办法放进去。

计算机技术当然也传到了亚洲大地,比如中国。
中国砖家们坐在一起发现,美国人搞的这个东西真的有问题,预留才128-255的空间,可是我们的汉字个数远远超出了这个数目啊,怎么办??
后面聪明的中国砖家们发现,只能使用2个字节了,否则真的搞不定。
由于必须和美国原来制定的ASCII不冲突,所以指定了如下规则
规则

  • 如果一个字节中第一位为0,那么这就是一个ASCII字符。
  • 如果一个字节中第一位为1,那么这个是汉字,认定需要2个字节才表示一个编码的文字。
    把这个码表叫GB2312
    这个码表中包含汉字6763个和非汉字图形字符682个。
    还有很多的空间没有用到,索性全部预留了吧。
    实现方式
  • 0xxxxxxx:表示为ASCII字符
    -1xxxxxxx 1xxxxxxx:表示为汉字

后来,中国砖家们发现,很多的不常用汉字没有在码表中,于是添加了很多的汉字进去,这个编码叫做GBK,实现方式和GB2312是完全一样的,兼容GB2312,当然也兼容ASCII。
实现方式

  • 0xxxxxxx:表示为ASCII字符
    -1xxxxxxx xxxxxxxx:表示为汉字

后面再次添加更多的字符进去,再次命名为GB18030,兼容GBK。由于汉字很多,2个字节并不能完全包括进去,所以GB18030采用2\4位混编的形式。

当然计算机也传到了日本(JIS)、韩国、台湾(BIG5)等等地方,大家全部发挥自己的聪明才智,各自实现了自己的编码。这些编码都与ASCII兼容,但是相互之间不兼容。

使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码,又称为"MBCS(Muilti-Bytes Charecter Set,多字节字符集)"。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码,所以在中文 windows下要转码成gb2312,gbk只需要把文本保存为ANSI编码即可。 不同ANSI编码之间互不兼容

第三阶段

随着通讯越来越多,而老美发现在自己公司需要国际化的时候,自己原来埋的这个雷真的害了自己。
于是乎,开始研讨把世界上几乎所有文字全部放在一个码表中,而这个包罗万象的码表就叫做Unicode,即万国码。
Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。
实际上,在软件制造商的协会(unicode.org)在做这个工作时,国际标准化组织(ISO)在做同样的事情,最后大家都意识到世界上并不需要两个不同的万国码,于是大家坐在一起合并研究的成果,最后的结果就是现在的Unicode。

各个编码及其范围

ASCII

编码范围00-7F,其中00-1F、FF为控制字符。其它为英文字母、数字、标点符号。

Latin1

编码范围00-FF,其中00-7F同ASCII,80-9F为控制符、9F-FF为字母和标点符号.

CP1252

微软的企业标准,补充了一些符号和欧元符号,为Latin1的超集。

GB2312

编码范围为A1A1-F7FE(剔除xx7F),共23940个码位。其中很多区间没有用到,而汉字使用的区间为B0A1-F7FE,其他为标点符号和特殊字符。
除常用简体汉字字符外还包括希腊字母、日文平假名及片假名字母、俄语西里尔字母等字符,未收录繁体中文汉字和一些生僻字。
对汉字进行了分区管理,其中第一个字节为区位码,包括下面区位。
01-09区为特殊符号。
16-55区为一级汉字,按拼音排序。
56-87区为二级汉字,按部首/笔画排序。
10-15区及88-94区则未有编码。
第二个字节为位字节,01-94总计94个。
为什么实际选择不是01-5E,而是选择A1-F7的位置呢?
因为英文可见字符区间为20-7F,加上128(也就是最高位为1)后得到的取件即是A1-FE
区位码使用了0xA1-0xF7(把01-87区的区号加上0xA0),位字节使用了0xA1-0xFE(把01-94加上 0xA0)

GBK

编码范围为8140-FEFE,兼容GB2312,仍然有部分区间没有用到。
GBK也支持希腊字母、日文假名字母、俄语字母等字符,但不支持韩语中的表音字符(非汉字字符)。GBK还收录了GB2312不包含的 汉字部首符号、竖排标点符号等字符。

CP936

CP936是微软指定的标准,属于企业标准,和GBK的有些许差别,绝大多数情况下可以把CP936当作GBK的别名。

BIG5

Big5是双字节编码,高字节编码范围是0x81-0xFE,低字节编码范围是0x40-0x7E和0xA1-0xFE。和GBK相比,少了低字节是0x80-0xA0的组合。0x8140-0xA0FE是保留区域,用于用户造字区。
Big5收录的汉字只包括繁体汉字,不包括简体汉字,一些生僻的汉字也没有收录。

CP950

微软的企业标准,可以理解为是对 Big5的扩展。

GB18030

编码范围同GBK,补充了更多的字符,由于Unicode开始流行且GB18030补充的字符都比较生僻,所以实际使用上基本是GBK。
GB18030编码是变长编码,有单字节、双字节和四字节三种方式。GB18030的单字节编码范围是0x00-0x7F,完全等同与ASCII;双字节编码的范围和GBK相同,高字节是0x81-0xFE,低字节的编 码范围是0x40-0x7E和0x80-FE;四字节编码中第一、三字节的编码范围是0x81-0xFE,二、四字节是0x30-0x39。

Unicode

中文的编码范围为4E00-9FCF,其中9FC4-9FCF之间的区间没有使用。
一个蛋疼的问题就是这个区间全部都是文字,中文标点没有包含在其中,中文标点散落在各个位置。详细请看http://blog.chinaunix.net/uid-12348673-id-3335307.html。
一些特殊的文字和中文部首以及一些特殊符号也不在此范围内,详细情况可以参考网址:http://www.cnblogs.com/sosoft/p/3456631.html

编码方面的一些概念

大尾(big endian)和小尾(little endian)

大尾和小尾是CPU处理多字节数的不同方式。例如“汉”字的Unicode编码是6C49。那么写到文件里时,究竟是将6C写在前面,还是将49写在前面?如果将6C写在前面,就是big endian。还是将49写在前面,就是little endian。

BOM

UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?
Unicode规范中推荐的标记字节顺序的方法是BOM,即Byte Order Mark。BOM是一个有点小聪明的想法:
在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。
这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF(读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。

Unicode的实现方式

Unicode只是进行了编码,也就是说只是一个码表,至于具体怎么实现,并没有规定。
下面是Unicode的几种实现方法。

UTF-8

范围 字节数 存储格式
0x0000~0x007F (0 ~ 127) 1字节 0xxxxxxx
0x0080~0x07FF(128 ~ 2047) 2字节 110xxxxx 10xxxxxx
0x0800~FFFF(2048 ~ 65535) 3字节 1110xxxx 10xxxxxx 10xxxxxx
0x10000~1FFFFFF(65536 ~ 2097152) 4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0x2000000~0x3FFFFFF 5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0x4000000~0x7FFFFFFF) 6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

理论上说,UTF-8并没有大小尾的困扰,所以并不需要BOM。
但是一些Windows应用会指定大小尾,比如Notepad,而且Excel在没有指定BOM的UTF-8文件进行读取时会使用Windows的codepage,从而出现错误。

UTF-16

在Unicode基本多文种平面定义的字符(无论是拉丁字母、汉字或其他文字或符号),一律使用2字节储存。而在辅助平面定义的字符,会以代理对(surrogate pair)的形式,以两个2字节的值来储存。
UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节 (2字节) 储存,但UTF-16却无法兼容于ASCII编码。
可以认为UTF-16是下面介绍的UCS-2的父集。在没有辅助平面字符(surrogate code points)前,UTF-16与UCS-2所指的是同一的意思。但当引入辅助平面字符后,就称为UTF-16了。现在若有软件声称自己支援UCS-2编码,那其实是暗指它不能支援在UTF-16中超过2bytes的字集。对于小于0x10000的UCS码,UTF-16编码就等于UCS码。
如果一个UTF-16文件没有指定BOM,默认应该是UTF-16BE,但是在Intel x86中却是UTF-16LE。所以在现实世界中有很多的没有指定大小尾的UTF-16却是UTF-16LE。

UTF-32

每一个Unicode码位使用恰好32位元。可以粗暴的认为UTF-32和下面要介绍的UCS-4是等同的。

UCS-2

采用2个字节,定长的表示每一个字符,所以总计可以表示2^16个字符。

UCS-4

UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个plane。每个plane根据第3个字节分为256行(rows),每行包含256个cells。当然同一行的cells只是最后一个字节不同,其余都相同。
group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中,高两个字节为0的码位被称作BMP。
将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。在UCS-2的两个字节前加上两个零字节,就得到了UCS-4的BMP。而目前的UCS-4规范中还没有任何字符被分配在BMP之外。

编码转换

请参考
字符编码之UCS-2与Utf-8
UCS-2和UTF-8的互相转换

操作系统使用编码

从Windows2K开始,Win的系统内核开始完全支持并完全应用Unicode编写,所有ANSI字符在进入底层前,都会被相应的API转换成Unicode。
Linux 服务器上 UCS-2 编码方式与 Winodws 不一致,以下是有关两个平台 UCS-2 编码的潜规则:

  1. UCS-2 不等于 UTF-16。 UTF-16 每个字节使用 ASCII 字符范围编码,而 UCS-2 对每个字节的编码可以超出 ASCII 字符范围。UCS-2 和 UTF-16 对每个字符至多占两个字节,但是他们的编码是不一样的。
  2. 对于 UCS-2, windows 下默认是 UCS-2LE。用 MultibyteToWidechar(或者A2W)生成的是 UCS-2LE 的 unicode。windows记事本可以将文本保存为 UCS-2BE,相当于多了层转换。
  3. 对于 UCS-2, linux 下默认是 UCS-2BE。用iconv(指定UCS-2)来转换生成的是 UCS-2BE 的 unicode。如果转换windows平台过来的 UCS-2, 需要指定 UCS-2LE。
  4. 鉴于windows和linux等多个平台对 UCS-2 的理解不同(UCS-2LE,UCS-2BE)。MS 主张 unicode 有个引导标志(UCS-2LE FFFE, UCS-2BE FEFF),以表明下面的字符是 unicode 并且判别 big-endian 或 little-endian。 所以从 windows 平台过来的数据发现有这个前缀,不用慌张。

对于JAVA/.NET/Python等这些“新”的语言来说,内置的字符串所使用的字符集已经完全是Unicode最重要的是,世界上大多数程序用的字符集都是Unicode,因为Unicode有利于程序国际化和标准化。

Python与编码

我会接着写另外一篇文章。

参考资料

    1. http://blog.chinaunix.net/uid-12348673-id-3335304.html
    2. http://demon.tw/programming/utf-16-ucs-2.html
    3. http://cryolite.iteye.com/blog/505011
    4. http://blog.chinaunix.net/uid-10468429-id-2953054.html
时间: 2024-08-03 15:35:50

编码发展历史的相关文章

Web开发技术发展历史

Web开发技术发展历史 来自:天码营 原文:http://www.tianmaying.com/tutorial/web-history Web的诞生 提到Web,不得不提一个词就是"互联网".Web是World Wide Web的简称,中文译为万维网."万维网"和我们经常说的"互联网"是两个联系极其紧密但却不尽相同的概念.今天"互联网"三个字已经承载了太多的内涵,提到互联网,我们通常想到的一种战略思维,或者是一种颠覆传统的商

Erlang cowboy 入门参考之现代Web的发展历史

Erlang cowboy 入门参考之现代Web发展史 原文: http://ninenines.eu/docs/en/cowboy/1.0/guide/modern_web/ 让我回顾一下web技术的发展历史,并可预见一下未来的发展.除了HTTP/2.0这个还未正式纳入规范的技术,Cowboy与所有这些技术都是兼容的. 早期的Web 起初的HTTP就是用来对GET请求返回HTML页面的.最初的版本是HTTP/0.9.HTTP/1.0定义了GET,HEAD和POST方法,能通过POST请求发送数

测试计算机软件发展历史

1.1    计算机软件发展历史 1.1.1 软件测试是伴随着软件的产生而产生的.早期的软件开发过程中,那时软件规模都很小.复杂程度低,软件开发的过程混乱无序.相当随意,测试的含义比较狭窄,开发人员将测试等同于“调试”,目的是纠正软件中已经知道的故障,常常由开发人员自己完成这部分的工作.对测试的投入极少,测试介入也晚,常常是等到形成代码,产品已经基本完成时才进行测试. 到了上世纪80年代初期,软件和IT行业进入了大发展,软件趋向大型化.高复杂度,软件的质量越来越重要.这个时候,一些软件测试的基础

python 学习之电脑的发展历史

电脑的发展历史 电脑的学名叫计算机,电脑是用来做计算的.在古时候,人们最早使用的计算工具可能是手指,英文单词“digit”既有“数字”的意思,又有“手指“的意思.古人用石头打猎,所以还有可能是石头来辅助计算.  缺点:手指和石头太低效了 后来出现了”结绳 “记事.   缺点:结绳慢,绳子还有长度限制. 又不知过了多久,许多国家的人开始使用”筹码“来计数,最有名的就要数咱们中国商周时期出现的算筹了.古代的算筹实际上是一根根同样长短和粗细的小棍子,大约二百七十几枚为一束; 多用竹子制成,也有用木头.

sql语言的发展历史

sql语言的发展历史 SQL是结构化查询语言(Structure Query Language)的缩写,它是使用关系模型的数据库应用语言,由IBM在70年代开发出来,作为IBM关系数据库原型System R的原型关系语言,实现了关系数据库中的信息检索. 80年代初,美国国家标准局(ANSI)开始着手制定SQL标准,最早的ANSI标准于1986年完成,它也被叫做SQL-86.标准的出台使SQl作为标准的关系数据库语言的地位得到加强.SQL标准几经修改和完善,目前新的SQL标准是1992年制定的SQ

选一种你比较熟悉的软件,并点评它的优缺点,并描述此类软件的发展历史

windows操作系统, 优点:图形化界面能够更加便捷的对文件进行处理 缺点:容易被黑客破解从而导致信息的丢失 发展历史: 1.Windows是由微软在1983年11月宣布,并在两年后(1985年11月)发行的. 2.Windows版本2.0是在1987.11正式在市场上推出的.该版本对使用者界面做了一些改进.2.0版本还增强了键盘和鼠标界面,特别是加入了功能表和对话框. 3.Windows3.0是在1990年5月22日发布的,它将Win/286和Win/386结合到同一种产品中.Windows

让你提前认识软件开发(24):C语言的发展历史和主要特点

第1部分 重新认识C语言 C语言的发展历史和主要特点 作为一门众所周知的计算机编程语言,C语言是谁发明的呢?它是如何演进的?它有何特点?到底有多少人在使用它? 1. C语言之父 C语言是1972年由美国贝尔实验室的计算机科学家Dennis Ritchie(丹尼斯·里奇)设计发明的.因此,Dennis Ritchie被誉为"C语言之父"(他已于2011年10月9日去世,享年70岁).图1中的人物就是Dennis Ritchie. 图1 "C语言之父" Dennis R

计算机芯片的发展历史——软件工程第一章第11题 范世良

软件的发展历史有有关的纪录片汇总: 纪录片名称 链接 Tetris: From Russia With Love Tetris: From Russia with Love ProJect Code Rush Project Code Rush The Pixar Story The Pixar Story id Software – All Your History id Software – All Your History Startup.com Startup.com The Histo

操作系统发展史,系统架构平台概览; Linux起源、理念、发展历史及各发行版

一.操作系统发展史 维基百科搜索操作系统 操作系统(英文:Operating System,缩写:OS)是管理计算机硬件与软件资源的计算机程序,同时也是计算机系统的核心与基石. 操作系统功能: · 进程管理(Processing management) · 内存管理(Memory management) · 文件系统(File system) · 网络通信(Networking) · 安全机制(Security) · 用户界面(User interface) · 驱动程序(Device driv