字符集和字符编码

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-8、UTF-16、UTF-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

时间: 2024-10-01 06:28:09

字符集和字符编码的相关文章

12.30 字符集和字符编码(Charset & Encoding)(转载)

——每个软件开发人员应该无条件掌握的知识! ——Unicode伟大的创想! 相信大家一定碰到过,打开某个网页,却显示一堆像乱码,如"б?ЯАзЪСЯ"."?????????"?还记得HTTP中的Accept-Charset.Accept-Encoding.Accept-Language.Content-Encoding.Content-Language等消息头字段?这些就是接下来我们要探讨的. 目录: 1.基础知识 2.常用字符集和字符编码 2.1. ASCII字符

字符集和字符编码(Charset & Encoding)

相信大家一定碰到过,打开某个网页,却显示一堆像乱码,如"б?ЯАзЪСЯ"."?????????"?还记得HTTP中的Accept-Charset.Accept-Encoding.Accept-Language.Content-Encoding.Content-Language等消息头字段?这些就是接下来我们要探讨的. 目录: 1.基础知识 2.常用字符集和字符编码 2.1. ASCII字符集&编码 2.2. GBXXXX字符集&编码 2.3. BI

(转)十分钟搞清字符集和字符编码

十分钟搞清字符集和字符编码 转载自: http://cenalulu.github.io/linux/character-encoding/作者: 卢钧轶 本文将简述字符集,字符编码的概念.以及在遭遇乱码时的一些常用诊断技巧 背景:字符集和编码无疑是IT菜鸟甚至是各种大神的头痛问题.当遇到纷繁复杂的字符集,各种火星文和乱码时,问题的定位往往变得非常困难. 本文就将会从原理方面对字符集和编码做个简单的科普介绍,同时也会介绍一些通用的乱码故障定位的方法以方便读者以后能够更从容的定位相关问题. 在正式

转:字符集和字符编码(Charset & Encoding)

转自:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html ——每个软件开发人员应该无条件掌握的知识! ——Unicode伟大的创想! 相信大家一定碰到过,打开某个网页,却显示一堆像乱码,如"б?ЯАзЪСЯ"."?????????"?还记得HTTP中的Accept-Charset.Accept-Encoding.Accept-Language.Content-Encoding.Content-L

【转载】十分钟搞清字符集和字符编码

十分钟搞清字符集和字符编码 什么是字符集 什么是字符编码 UTF-8和Unicode的关系 UTF-8编码简介 为什么会出现乱码 如何识别乱码的本来想要表达的文字 常见问题处理之Emoji 本文将简述字符集,字符编码的概念.以及在遭遇乱码时的一些常用诊断技巧 背景:字符集和编码无疑是IT菜鸟甚至是各种大神的头痛问题.当遇到纷繁复杂的字符集,各种火星文和乱码时,问题的定位往往变得非常困难.本文就将会从原理方面对字符集和编码做个简单的科普介绍,同时也会介绍一些通用的乱码故障定位的方法以方便读者以后能

我对字符集和字符编码的理解

先定义两个概念. 字符集 字符集就是把字符和一串数字(码点)一一对应起来.GB2312,GBK,UNICODE,这些都是字符集. 字符编码 字符编码就是取得字符集中和字符对应的那串数字(字符编码)之后,基于取得的那串数字再生成另外一串数字.utf8,utf16,utf32这些都是字符编码. 字符集和字符编码的关系 我们可以把字符集看作一个函数,F(字符)=string1 我们也可以把字符编码看作另外一个函数,G(F(字符))=string2 string1即可以等于string2,也可以不等.

字符乱码之字符集和字符编码

最近经常会碰到上传客户提供的历史数据上传时csv文件用Excel打开时会有乱码问题,虽然知道知道是字符编码不一致导致的,但其中诸多细节却知之甚少,今日特来理理. 1.为什么会有字符乱码问题?如何解决字符乱码问题 计算机中存储的信息都是二进制数表示的,但是世界上有各种不同的语言文字,所以我们需要一些规则将各种字符转换成二进制后存储在计算机中 即编码,以及如果将存储在计算机中的二进制数解析出来即解码.就如破译电报密码一样如果密码本是错误的,那么密码也是错误.会有字符乱码问题就是因为解码方式是不对的,

字符集和字符编码的区别

转自:https://www.cnblogs.com/xdyixia/p/9114145.html 1.字符,字符集,字符编码概念 字符:在计算机和电信技术中,一个字符是一个单位的字形.类字形单位或符号的基本信息.即一个字符可以是一个中文汉字.一个英文字母.一个阿拉伯数字.一个标点符号等. 字符集:多个字符的集合.例如GB2312是中国国家标准的简体中文字符集,GB2312收录简化汉字(6763个)及一般符号.序号.数字.拉丁字母.日文假名.希腊字母.俄文字母.汉语拼音符号.汉语注音字母,共 7

2015/5/1 (二) 字符集和字符编码

首先,我们需要了解,计算机硬件是只会读取二进制文件的,但是,对于这些复杂的10110101101,这些东西所表达的意思,即使是高深的程序猿们,也未必看得懂,就更别说那些不是IT行业的人士了,但是,随着计算机的普及,自然而然地,就有人站出来解决这个人与计算机交流的问题了.第一个登场亮相的就是ASCII这个东西,全称American Standard Code for Information Interchange,即是美国标准信息交换代码  下面附图: 简单来说,这就是一个标准,跟语言一样,这个这