字符编码概述

字符编码概述

字符编码发展历史  字符集

ASCII 和ISO/IEC 0646

  ASCII(pronunciation: /æski/ ASS-kee[1],American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语,而其扩展版本EASCII则可以勉强显示其他西欧语言。它是现今最通用的单字节编码系统(但是有被Unicode追上的迹象),并等同于国际标准ISO/IEC 646。
  ISO/IEC 646是国际标准化组织(ISO)和国际电工委员会(IEC)于1972年制订的标准。它是一个 7-位元字符的字集,来自数个国家标准,最主要来自美国的 ASCII(美国信息互换标准代码)。ISO 646 除了英语字母和数字部分,为所有国家相同外,有些使用字母的国家,可按照实际需要,把 ISO 646 修改,以定出该国的字符标准。亦因为当年 8-位元字符集并未得到普遍接纳,各国把不同的字母或符号放进它们的字符集,以致部分出现在 ASCII 的字母或符号,并没有出现在某些国家的 ISO 646 变体之中。
  ASCII第一次以规范标准的型态发表是在1967年,最后一次更新则是在1986年,至今为止共定义了128个字符;其中33个字符无法显示(这是以现今操作系统为依归,但在DOS模式下可显示出一些诸如笑脸、扑克牌花式等8-bit符号),且这33个字符多数都已是陈废的控制字符。控制字符的用途主要是用来操控已经处理过的文字。在33个字符之外的是95个可显示的字符,包含用键盘敲下空白键所产生的空白字符也算1个可显示字符(显示为空白)。
 
  ASCII是最原始的计算机编码,由于计算机由美国人发明,所以最原始的ASCII码只考虑了所有的美字母和相关的字符。

http://zh.wikipedia.org/zh-cn/ASCII

EASCII

  计算机逐渐应用到欧美,ASCII码渐不能满足新的应用,在此情况下,ASCII的最大缺点是只能显示26个基本拉丁字母、阿拉伯数目字和英式标点符号,因此只能用于显示现代美国英语(而且在处理英语当中的外来词如 naïve、café、élite等等时,所有重音符号都不得不去掉,即使这样做会违反拼写规则)。


 

ISO/IEC 8859

     同样是因为各国语言环境差异,EASCII码也不能统一满足以欧美为主的地区的需求,EASCII开始出现多个版本,为了统一规范,出现在ISO8859-n系列的规范,本质上都是对ASCII码的扩充。0-127位完全兼容ASCII码,高位各版本略有差异,在0xA0-0xFF根据不同字符集放入不同的字符。
    各种ISO 8859字符集:
    * 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号本来是预留给印度天城体梵文的,但后来却搁置了。


 
https://zh.wikipedia.org/wiki/ISO/IEC_8859

ISO/IEC 2022

  ISO 2022,全称ISO/IEC 2022,由国际标准化组织(ISO)及国际电工委员会(IEC)联合制定,是一个使用7位编码表示汉语文字、日语文字或朝鲜文字的方法。

ISO 2022等同于欧洲标准组织(ECMA)的ECMA-35、中国国标GB 2312、日本工业规格JIS X 0202(旧称JIS C 6228)及韩国工业规格KS X 1004(旧称KS C 5620)。
英语可用7位编码储存,而其他使用拉丁字母、希腊字母、西里尔字母、希伯来字母等的语文,由于只使用数十个字母,传统上均使用8位编码的ISO/IEC 8859标准来表示。但由于汉语、日语及朝鲜语字数众多,无法用单一个8位字符来表达,故需要多于一个字节来代表一个字。于是,ISO 2022就设计出来让汉语、日语及朝鲜语可以使用数个7位编码的字符来示。
  ISO 2022使用“逃逸字串”(Escape sequence)。逃逸字串由1个“ESC”字符(0x1B),再由两至三个字串组成。此标记代表它后面的字符,属于下表字符集的文字。
就多字节扩充编码的国际标准ISO2022而言,两个8位的位元组只能提供最多188个控制字符和35,344个文字形符号的编码空间,共计35,532 个编码位置,但是16个位的编码空间事实上高达65,536。两者相比较,ISO2022的16位编码只能达到最大编码空间的54%,显得利用率很差。同 时在应用层次的编码,由于厂商众多又缺乏共识,往往你编你的码、我编我的码,其后果则是引发万码奔腾的乱象。
http://zh.wikipedia.org/wiki/ISO/IEC_2022

ANSI

  ISO8859解决了英语语系国家的文字问题,但对更多其他非英语文字依然无能为力。这时各国家地区分别推出了符合自己国家文字的字符集标准,不同的国家和地区制定了不同的标准。如中国的简体中文集(gb2312)、以及后来的GBK,日本的JIS等。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。 不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。 当然对于ANSI编码而言,0x00~0x7F之间的字符,依旧是1个字节代表1个字符。这一点是ASNI编码与Unicode编码之间最大也最明显的区别。

同时,这也是编码标准最混乱的时代。

扫描二维码关注公众号,回复: 5114937 查看本文章
  关于ansi编码的BUG
  很多细心的人会发现,当新建文本文档只输入“联通”2字保存再打开时将是乱码。当txt文档中一切字符都在 C0≤AA≤DF 80≤BB≤BF 这个范围时,notepad都无法确认文档地格式,没有自动依照UTF-8格式来"Display"。 而"联通"就是C1 AA CD A8,刚好在上面地范围内,所以不能正常显现。记事本默认是以ANSI编码保存文本文档的,而正是这种编码存在的bug招致了上述怪现象。假如保存时选择Unicode、Unicode(big endian)、UTF-8编码就正常了。此外,假如以ANSI编码保存含有某些特别符号的文本文档,再次打开后符号也会变成英文问号。
注:ANSI也是兼容ASCII码的
http://baike.baidu.com/view/1273097.htm


ISO/IEC 10646 UCS
  通用字符集(Universal Character Set,UCS)是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的标准字符集。UCS-2用两个字节编码,UCS-4用4个字节编码。
  为容纳全世界各种语言的字符和符号,ISO的一些会员国于1984年发起制定新的国际字符集编码标准。新标准由工作小组ISO/IEC JTC1/SC2/WG2(注1)负责拟订(以下简称WG2),最后定案的标准命名为“Universal Multiple-Octet Coded Character Set”(简称UCS),其编号则订为ISO/IEC 10646。依WG2原来的规划,ISO10646的编码结构系沿袭ISO2022八位延伸编码结构以避开C0和C1两个句柄区(注2),但打破每个字符 码里的所有字节的bit-8(即最左边的位,其值为28=128)必须都设为0或是都设为1的限制,以提高编码空间的使用率。同时,为了能有足够位置以容 纳全世界各种语言的字符和符号,以及为了配合微处理器以8、16、32甚或64个位为一个运算处理单位的趋势,ISO10646的字符码长度被规定为定长 的4个八位(octet)。
http://server.it168.com/server/2007-06-25/20070625012201.shtml
http://zh.wikipedia.org/wiki/ISO_10646

注2:C0句柄区指的是编码为0~31的32个句柄(其bit-8为0),而C1句柄区则是意指128~159的32个句柄(其bit-8为1)。关于C0和C1句柄详情,请参考ISO6429或CNS13479。

Unicode
  Unicode(Universal code、统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。
Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。

Unicode和ISO 10646(UCS)
  ISO10646草案初稿一经公布,其编码结构立即遭到美国部份计算机业者的反对。1988年初,美国Xerox公司的Joe Becker倡议以新的编码结构,另外编订世界性字符编码标准:将计算机字符集编码的基本单位由现行的7或8个位一举扩充为16个位,并且充分利用 65,536个编码位置以容纳全世界各种语言的字符和常用符号。新的字符集编码标准被命名为“Unicode”(注3)。一群来自Xerox公司和 Apple公司的工程师组成工作小组,负责Unicode的原始设计工作。1991年元月,十多家计算机硬软件、 网络和信息服务业者,包括:IBM、DEC、Sun、Xerox、Apple、MicroSoft、Novell名公司,共同出资成立Unicode协会 (The Unicode Consortium),并由协会设立非营利的Unicode公司。Unicode协会成立之后,将原先的工作小组扩编为Unicode技术委员会 (Unicode Technical Committee),专责Unicode的字符搜集、整理、编码等工作。推动Unicode成为国际标准的工作,则由Unicode公司负责。 Unicode草案第一版于1989年9月发表,历经多次修订后,分别于1991、92年出版了Unicode标准第一版(The Unicode Standard, version 1.0)的第一、第二册。    
  1991年前后,两个项目的参与者都认识到,世界不需要两个不兼容的字符集。于是,它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作。WG2放弃原先选择的ISO2022八位延伸编码结构,改采Unicode的编码方式,亦即连续编码不再避 开C0和C1句柄区。1991年10月,历经几个月的协商之后,WG2和Unicode协会达成协议,将Unicode并入ISO10646成为第0字 面。之后各国语言字元的搜集、整理和编码等工作转由WG2主导,而Unicode协会则积极协助WG2,但双方仍然各自出版自己的编码标准

  从Unicode 2.0开始,Unicode采用了与ISO 10646-1相同的字库和字码;ISO也承诺,ISO 10646将不会替超出U+10FFFF的UCS-4编码赋值,以使得两者保持一致。两个项目仍都存在,并独立地公布各自的标准。但统一码联盟和ISO/IEC JTC1/SC2都同意保持两者标准的码表兼容,并紧密地共同调整任何未来的扩展。在发布的时候,Unicode一般都会采用有关字码最常见的字型,但ISO 10646一般都尽可能采用Century字型。

Unicode和ISO 10646的异同
  统一码联盟公布的Unicode标准包含了ISO/IEC 10646-1实现级别3的基本多文种平面。在两个标准里,所有的字符都在相同的位置并且有相同的名字。

ISO/IEC 10646标准,就像ISO/IEC 8859标准一样,只不过是一个简单的字符集表。它定义了一些编码的别名,指定了一些与标准有关的术语,并包括了规范说明,指定了怎样使用UCS连接其他ISO标准的实现,比如ISO/IEC 6429和ISO/IEC 2022。还有一些与ISO紧密相关的,比如ISO/IEC 14651是关于UCS字符串排序的。



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

UTF-32与UCS-4
  UTF-32 (或 UCS-4)是一种将Unicode字符编码的协定,对每一个Unicode码位使用恰好32位元。其它的Unicode transformation formats则使用不定长度编码。
因为UTF-32对每个字符都使用4字节,就空间而言,是非常没有效率的。特别地,非基本多文种平面的字符在大部分文件中通常很罕见,以致于它们通常被认为不存在占用空间大小的讨论,使得UTF-32通常会是其它编码的二到四倍。FFFFFF,所以其空间约20亿个码位。有些人认为保留如此大的字码空间却只为了对应这很小的码集是浪费的所以一个新的编码UTF-32被提出来了。UTF-32 是一个 UCS-4 的子集,使用32-位元的码值,只在0到10FFFF的字码空间(百万个码位)。UTF-32 原本是 UCS-4 的子集,但JTC1/SC2/WG2声明,所有未来对字符的指定都将会限制在BMP及其14个补充平面。于是就现状而言,除了 UTF-32 标准包含额外的 Unicode 意涵,UCS-4 和 UTF-32 大体是相同的。

UTF-8

  UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码(定长码),也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。


  UTF-8的编码方式
  UTF-8是UNICODE的一种变长度的编码表达方式《一般UNICODE为双字节(指UCS2)》,它由Ken Thompson于1992年创建,现在已经标准化为RFC 3629 。UTF-8就是以8位为单元对UCS进行编码,而UTF-8不使用大尾序和小尾序的形式,每个使用UTF-8存储的字符,除了第一个字节外,其余字节的头两个比特都是以"10"开始,使文字处理器能够较快地找出每个字符的开始位置。但为了与以前的ASCII码兼容(ASCII为一个字节),因此UTF-8选择了使用可变长度字节来存储Unicode:


Unicode和UTF-8之间的转换关系表

UCS-4 编码        UTF-8字节流
U+00000000   –   U+0000007F    0xxxxxxx
U+00000080   –   U+000007FF    110xxxxx 10xxxxxx
U+00000800   –   U+0000FFFF    1110xxxx 10xxxxxx 10xxxxxx
U+00010000   –   U+001FFFFF    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U+00200000   –   U+03FFFFFF    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

U+04000000   –   U+7FFFFFFF    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

  在ASCII码的范围,用一个字节表示,超出ASCII码的范围就用字节表示,这就形成了我们上面看到的UTF-8的表示方法,这様的好处是当 UNICODE文件中只有ASCII码时,存储的文件都为一个字节,所以就是普通的ASCII文件无异,读取的时候也是如此,所以能与以前的ASCII文 件兼容。 大于ASCII码的,就会由上面的第一字节的前几位表示该unicode字符的长度,比如110xxxxxx前三位的二进制表示告诉我们这是个 2BYTE的UNICODE字符;1110xxxx是个三位的UNICODE字符,依此类推;xxx的位置由字符编码数的二进制表示的位填入。越靠右的x 具有越少的特殊意义。只用最短的那个足够表达一个字符编码数的多字节串。注意在多字节串中,第一个字节的开头"1"的数目就是整个串中字节的数目。
  ASCII字母继续使用1字节存储,重音文字、希腊字母或西里尔字母等使用2字节来存储,而常用的汉字就要使用3字节。辅助平面字符则使用4字节。
在UTF-8文件的开首,很多时都放置一个U+FEFF字符(UTF-8以EF,BB,BF代表),以显示这个文本文件是以UTF-8编码。


附1:Big Endian 与 Little Endian

BigEndian(大端存储)、Little Endian(小端存储)
上面提到了一个字符可能占用多个字节,那么这多个字节在计算机中如何存储呢?比如字符0xabcd,它的存储格式到底是 AB CD,还是 CD AB 呢?
实际上两者都有可能,并分别有不同的名字。如果存储为 AB CD,则称为Big Endian;如果存储为 CD AB,则称为Little Endian。
具体来说,以下这种存储格式为Big Endian,因为值(0xabcd)的高位(0xab)存储在前面:
地址值0x00000000AB 0x00000001CD
相反,以下这种存储格式为Little Endian:
地址值0x00000000CD 0x00000001AB


附2:BOM
  在Unicode/UCS编码的文本文件的首部,可能附加几个字节作为字符集的标识,当然也可以不附加。如以下几种
字符集    字节标识
UTF-8                                    EF,BB,BF
Unicode-BE/UTF-16BE     FE FF
Unicode-LE/Unicode         FF FE

附3:更多字符编码
 



猜你喜欢

转载自blog.csdn.net/trocp/article/details/8137479