码迷,mamicode.com
首页 > 其他好文 > 详细

字符集和字符编码

时间:2015-10-19 00:37:55      阅读:250      评论:0      收藏:0      [点我收藏+]

标签:

1. 概述

    现在的编程语言对字符串的处理一般封装比较好,所以平时编写代码,很少要自己考虑字符编码问题。以前学习xml时,由于xml的存储涉及到编码格式,查过一些资料,知道一些概念,GB2312、Unicode、Utf-8、Utf-16、UCS-2等,但这些概念之间什么关系,仍然一知半解。最近要做国际化,需要把不支持Unicode的程序升级为Unicode,借着这个机会,把其中的知识梳理了一遍,对字符编码的理解算更系统化了,在此总结一下。

 

2. 字符集和字符编码

  首先明确两个概念,“字符集”(charset)和“字符编码(encoding)”。有些地方经常把这两个概念等同,比如说到ASCII码,有时候指“字符集”,有时候指“字符编码”,其实这是两个不同的概念,混淆了这两个概念,很难真正理解一些概念,比如Unicode和Utf8、Utf16的关系(其实Unicode是字符集和第一层字符编码,Utf8、Utf16是第二层字符编码,它们都表示了同一个字符集)。

    字符集顾名思义是“许多字符的集合”,这些字符组成一套符号系统,可以组合起来形象的表达各种含义。比如26个英文字母加上标点符号可以组成“英文字符集”,这个字符集的组合可以形成英美人可以理解的一套文字系统,看到了“I love you”,就能明白什么意思。再比如新华字典中的所有汉字加上标点符号可以组成“中文字符集”,这个字符集的组合可以形成中文文字系统,看到“我爱你”就能理解其含义。对于老外,如果不懂中文,看到“我爱你”三个字符,可能以为就是“鬼画符”。

  “字符编码”字面意思就是“对字符进行编码”。呵呵,听起来有点废话。那先说下为什么要对字符进行编码。对字符编码的最大目的还是为了传输、储存信息(其实储存也是为了传输,是为了能传给以后的人看)。人和人之间交流,无非两种方式:口头交流,书面交流。书面交流就是把“字符”“画”到纸上或者其他介质上,然后传输给别人看。但是当传输过程遇到了特殊情况,就出现问题了。比如下面三种情况:

  1. 盲人和他人书面交流。
  2. 军队要传递情报,防止被敌军截获泄密。  
  3. 采用了新的传输、存储技术。比如电报、计算机。

  盲人和他人之间的书面交流采用盲文。国际上的盲文又叫六点盲文,是法国人路易·布莱尔(Louis Braille)于1824年发明的【1】。此前盲文就是普通的文字,只是印刷制作比较特殊,采用凸起的文字,便于触摸。但是学习、使用起来非常复杂,书写、阅读都很困难。路易·布莱尔上学时候,有个海军军官查尔斯·巴比埃给他们讲了一种“夜间书写”法符号,它是一种用两行各6个凸点的符号来表示各种音标的方法,是专为夜间作战时传递命令和加强联络而创造的。布莱尔由此受到启发,后来潜心研究,终于发明了六点盲文。

  六点盲文由63个编码字符组成,每个字符由1~6个突起的点儿安排在一个有6个点位的长方形里。为了确认63个不同的点式或盲文字符,数点位时是左起自上而下1—2—3,然后右起自上而下4—5—6。这些凸起在厚纸上的行行盲文,可以用手指轻轻摸读。六点盲文可以看作盲人书面交流的一种字符编码。

技术分享

六点盲文字符集及编码【1】

  情报传递的方法比较多了,主要采用字符加密的方法以防止泄密。加密过程本身就是一种字符编码的过程,把能够看懂的文字通过某种算法,变成杂乱无章毫无意义的文字;或者把文字拆散,分布在许多毫无关系的文字中。接收方收到以后,再按照相反的方法还原,进行解码得到对方的真实信息。

  电报的传输通常使用“莫尔斯电码”。抗日剧、抗日电影中经常听到这种发报机的声音,“嘀,嘀嘀,嘀嘀嘀嘀……”。它的诞生,就是为了能用电信号传输文字。莫尔斯电码主要由点、划组成,比如“.-”表示“A”,“-...”表示“B”,可以通过发报机以脉冲电流的方式发送。发报方把文字编码,转成莫尔斯电码,接收方再解码,还原成文字。

    电报现在虽然不再使用,莫尔斯电码在一些关键场合可能还会用到。“SOS”是国际救援信号,但它并非单词的缩写。二十世纪初,海难事件频繁发生,往往由于不能及时发出求救信号和最快组织施救,结果造成很大的人员伤亡和财产损失,后来国际无线电报公约组织于1908年正式将它确定为国际通用海难求救信号【2】。这三个字母组合没有任何实际意义,只是因为它的电码“ ...---...”(三个圆点,三个破折号,然后再加三个圆点)在电报中是发报方最容易发出,接报方最容易辨识的电码。1912年泰坦尼克号成为海事史上第一艘发出SOS求救信号的船【3】

  计算机诞生以后,面临跟电报同样的问题——计算机只有电子信号0和1,字符的形状对于它来说没有任何意义,如何表示各种文字符号呢?这样就产生了各种计算机字符集和字符编码——ASCII、Unicode等。

 

3. 字符编码的四个步骤

  从上一节来看,“字符集”是一种形象表意的工具,“字符编码”是表示字符的一种方式。在计算机出现之前就已经有了这两种技术。计算机中,是使用二进制的方式对字符集重新编码。

    在计算机中,要建立一种“字符编码模型”,需要四步【4】

  1. 要有一个字符库,确定这些字符足够表意。 比如ASCII字符集,已经足够表示英语,但不能表示中文,于是产生GB2312字符集。
  2. 第一层编码,给每个字符编个数字。比如ASCII字符集中,65表示“A”,97表示“a”。
  3. 第二层编码,确定表示字符的二进制位数(8位,16位,32位)。ASCII使用7位,DBCS(双字节字符集)使用16位。
  4. 第三层编码,确定字符二进制值的存储格式(大端法,小端法)。比如X86机器使用小端法。

    一种字符集一般只有一种编码方式,当字符集不够用时,会增加一些新的符号,形成新的字符集。对于新的符号会有新的数字,新的编码格式。所以有时“字符集”和“字符编码”的概念并不严格区分。比如ASCII码,可以指128个字符的字符集,也可以指对这128个字符的编码方式。不过有的字符集有多种编码格式,比如Unicode字符集,Utf8、Utf16都是其编码格式(第二层编码)。

 

4.常用计算机编码

    了解了“字符集”和“字符编码”的概念,下面说说计算机中的各种编码,及其来龙去脉。

 

4.1.ASCII码

  全称“American Standard Code for Information Interchange”,美国标准信息交换码,由美国标准委员会(American Standards Association,简称ASA)制定,后来该协会改组为“美国国家标准学会”(American National Standard Institute , 简称ANSI ),所以很多资料上说ASCII码是ANSI制定的。ASCII码是从电报码发展过来的,最早使用是用在7-bit的电传打字机上的【5】。1960年10月6日,ASA开始ASCII的标准化工作,于1963年发布第一版,1967年再发布一次大的版本,这个标准版本,也是一个7-bit码,包含33个非打印字符(许多已经废弃了),95个打印字符(包含空格符)【5】

技术分享

1972年打印机手册上的ASCII表【5】

  详细介绍,可以参见【5】维基百科-ASCII,百度百科中讲得比较笼统,有时候误用其表示其他含义,很容易引起混淆。

    注意,这个最初是美国的标准,包含的95个打印字符中,无法囊括世界上所有国家的字符,比如英镑符号“£”,各种拉丁符号“δ、β、θ”,中文、日文、韩文这么多象形文字等等。为了解决这个问题,各国都制定了自己的字符集和字符编码,不过,基本上都兼容7-bti ASCII码。比如ISO-8859系列,日文的JIS,中国大陆的GB2312、GBK,台湾的Big5等。

4.2. Extended ASCII码

  最初的标准ASCII码中包含的字符太少,很多应用或者国家中的符号都无法表示。比如数学符号“× ÷ ≠ ≥ ≈ π”。尤其20世纪70年代,随着PC的兴起,各电脑厂商开始增加自己的图形符号,形成了各种非标准的扩展ASCII码字符集(比如,ATASCIIPETSCII等)。TRS-80(美国早期的一种家庭电脑),增加了32个图形字符【6】

  当时的IBM也为自己的PC定制了8-bit扩展ASCII码字符集,叫做代码页(code page),给不同语言制定不同的 code page,并把这些 code page 编号。这些 code page 都是兼容标准ASCII的。比如,北美市场的DOS电脑,使用 code page 437,包含了法语、德语和一些其他欧洲国家的带音调的字符【6】。code page 技术一直保留了下来,发展到现在,微软的windows内部就用了这种技术。

  苹果电脑也在 Mac OS 系统中引入了自己的8-bit扩展ASCII编码,如 Mac OS Roman。国家的带音调的字符【6】

  DEC公司也开发了 MCS(Multinational Character Set,多国字符集)【6】

 

4.3 ISO-8859

  由于各公司、国家之间都有自己的字符集,同一个数值,在不同的字符集之间表示的符号可能不一样,这样在一台电脑上正常可以阅读的文件,到另外一台电脑可能就成了乱码。为了解决这个问题,ISO组织统一了一套标准字符集,就是ISO-8859.不过 ISO-8859 不是一个字符集,而是一系列扩充的ASCII码字符集。如下【7】

  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号本来是预留给印度天城体梵文的,但后来却搁置了。

 

4.4. MBCS、DBCS

  上面所说的ASCII码、扩展ASCII码、ISO-8859中每个字符都是一个字节(8-bit)可以表示的,所以称为“单字节字符集”。单字节字符集最多只能同时表示256个字符,ISO-8859中总字符数可能超过256个,但同时能使用的字符要么是8859-1字符集中的,要么是8859-2字符集中的,每个字符集最多仍然是256个,如果一篇文章中要出现所有语系中的字符,也是做不到的。

  但是到了亚洲,中、日、韩等国家文字,每个文字都是一个符号,远远超过256个字符。于是,亚洲国家制定了自己的字符集,使用2个或以上的字节数表示自己的字符集,这就是“多字节字符集”(Multi-Bytes Character Sets,简称MBCS)。

  windows 系统中,在 MBCS 下,字符以 1 或 2 字节进行编码,由于大部分字符是2字节的,所以又称为“双字节字符集”(Double-Bytes Character Sets,简称DBCS),所以有的时候看到MBCS、DBCS,都是一回事。MBCS是完全兼容标准ASCII码的。

 

4.5. GB2312、GB13000、GBK、GB18030

  1980年,中国制定了自己的字符集标准,全称为《信息交换用汉字编码字符集--基本集》,简称GB2312-80,一共收录了 7445 个字符,包括 6763 个汉字和 682 个其它符号。GB2312-80,简称为GB2312

  1993年,国际标准Unicode 1.1版本推出,收录中国大陆、台湾、日本及韩国通用字符集的汉字,总共有20,902个。中国大陆制定了等同于Unicode 1.1版本的“GB 13000.1-93”,简称为GB13000。

  GB13000显然包含GB2312已有的文字和其他很多为包含的文字,如GB2312-80推出以后才简化的汉字(如“啰”),部分人名用字(如中国前总理朱镕基的“镕”字),台湾及香港使用的繁体字,日语及朝鲜语汉字等。

  GBK全称《汉字内码扩展规范》(GBK即“国标”、“扩展”汉语拼音的第一个字母,英文名称:Chinese Internal Code Specification) ,中华人民共和国全国信息技术标准化技术委员会1995年12月1日制订,国家技术监督局标准化司、电子工业部科技与质量监督司1995年12月15日联合以技监标函1995 229号文件的形式,将它确定为技术规范指导性文件。这一版的GBK规范为1.0版【8】 

  国家标准GB18030-2005《信息技术中文编码字符集》是我国继GB2312-1980和GB13000.1-1993之后最重要的汉字编码标准,是我国计算机系统必须遵循的基础性标准之一。 GB18030有两个版本:GB18030-2000和GB18030-2005。GB18030-2000是GBK的取代版本,它的主要特点是在GBK基础上增加了CJK统一汉字扩充A的汉字。GB18030-2005的主要特点是在GB18030-2000基础上增加了CJK统一汉字扩充B的汉字【9】

4.6. ANSI 编码

  ANSI愿意是指美国国家标准协会,但是在windows系统中,ANSI编码意思却代表“本地编码”。也就是说,在中国代表GBK,在台湾代表Big5,在日本代表JIS,所以windows编程中常说的ANSI字符串,就是指本地编码的字符串,在中国,就是一种DBCS,用1个和2个字节表示一个字符的编码。

  为什么ANSI编码等同于本地编码?在微软的MSDN中找到一些说明:

  早期,windows 中的英语和西欧字符集 code page 1252,是在ANSI草案基础上制定的,这个草案最后发展成ISO 8859-1,由此看来code page 1252 是早于ISO 8859-1标准的。因为这个,windows code page,通常被称为“ANSI code page”。

  windows code page 有时候也指“系统活动代码页”,一个windows操作系统,总会有一个当前的活动代码页,也就是“本地代码页”。

  可能因为这个原因,ANSI编码等同于本地编码。

  不过也可以这么理解:ANSI编码本来只包含了英文编码,后来到了各国,在ANSI编码基础上扩展成了本地编码,所以ANSI编码也可以指本地编码,ANSI字符串也表示本地字符串。

 

4.7. Unicode、UCS

  以上的编码都是本地化编码,一国之内还没有问题,但是要跨国,就不行了。有没有一个字符集,能包含世界上所有的字符呢?这就是Unicode字符集。

  明天待续……先去睡觉!

 

4.8. UTF-8UTF-16UTF-32

5.各种字符编码之间的关系

  1、单字节字符集

  2、多字节/双字节字符集

  3、宽字符

 

 

参考文档:

【1】百度百科,《盲文》,http://baike.baidu.com/view/23057.htm

【2】百度百科,《SOS》,http://baike.baidu.com/subview/1744/5037817.htm

【3】松田行正,《零ZERO:世界符号大全》,中央编译出版社

【4】Peter Constable,《Character set encoding basics》,SIL,2001-06-13:http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&item_id=IWS-Chapter03#0d7ccb25

【5】维基百科,《ASCII》,https://en.wikipedia.org/wiki/ASCII

【6】维基百科,《Extended ASCII》,https://en.wikipedia.org/wiki/Extended_ASCII

【7】百度百科,《ISO-8859》,http://baike.baidu.com/view/9753105.htm

【8】百度百科,《GBK字库》,http://baike.baidu.com/view/931619.htm

【9】百度百科,《gb18030》,http://baike.baidu.com/view/889058.htm

【10】Crifan Li,《字符编码详解》http://www.crifan.com/files/doc/docbook/char_encoding/release/html/char_encoding.html#enc_unicode

字符集和字符编码

标签:

原文地址:http://www.cnblogs.com/notbecoder/p/4840783.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!