字符编码2

字符编码

 

字符编码,近年来一直困扰着我,感觉平常遇到的UTF-8,GBK,Unicode,ANSI等编码大致知道意思也就可以了,没有必要去给它一个细分。

但是,今天发现不得不去好好梳理一下他们的关系了。因为这个地方老是出些莫名其妙的问题。

1. 字符集和字符编码

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

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

  “字符编码”字面意思就是“对字符进行编码”。呵呵,听起来有点废话。那先说下为什么要对字符进行编码。对字符编码的最大目的还是为了传输、储存信息(其实储存也是为了传输,是为了能传给以后的人看)。

字符编码的四个步骤

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

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

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

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

 

2 常用计算机编码

2.1 ASCII码

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

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

2.2 Extended ASCII码

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

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

  苹果电脑也在 Mac OS 系统中引入了自己的8-bit扩展ASCII编码,如 Mac OS Roman。国家的带音调的字符。DEC公司也开发了 MCS(Multinational Character Set,多国字符集)。

 

  其实标准的ASCII就是7-bit的编码(8字节,但是最高位没有编码),后来使用过程中发现127个字符有点不够用,于是将ASCII进行了扩展,叫做Extended-ASCII或者high-ASCII,8位的,能表示256个字符。由于不同的应用场景,有不同的编码,有IBM的Extend ASCII和ANSI的Extend ASCII。去wikipedia上会发现有好多种ASCII的标准,大类就是IBM和ANSI(Windows的,微软很强势,ANSI的东西感觉就是给他们家用的)两种,其实都是为了给自家系统用的,随着IBM操作系统的坠落,IBM的扩展ASCII也基本上淡出视野。

wikipedia,Revisions of the ASCII standard:
    ASA X3.4-1963[1][4][16][17]
    ASA X3.4-1965 (approved, but not published, nevertheless used by IBM 2260 & 2265 Display Stations and IBM 2848 Display Control)[1]:423, 425–428, 435–439[16][17]
    USAS X3.4-1967[1][5][17]
    USAS X3.4-1968[1][17]
    ANSI X3.4-1977[17]
    ANSI X3.4-1986[7][17]
    ANSI X3.4-1986 (R1992)
    ANSI X3.4-1986 (R1997)
    ANSI INCITS 4-1986 (R2002)[18]
    ANSI INCITS 4-1986 (R2007)[19]
    ANSI INCITS 4-1986 (R2012)
wikipedia--Revisions of the ASCII standard

  看到没,早期有四个版本是IBM的。


  扩展的ASCII的产生
  既然IBM的扩展ASCII已经成为昨日黄花,我们只考虑ANSI的扩展ASCII的出现契机。
搭载Windows系统的计算机进入欧洲之后,发现标准的ASCII并不能满足欧洲这些拉丁语族国家的语言表意,决定对其进行扩展。同为印欧语系,发现扩展起来也没那么难,总共256个值就包括所有了。只需要将原来的7-bit扩展为8-bit,将原来的标准ASCII保留,第一位使用0来表示。将扩展的字符第一位使用1来表示

  扩展ASCII的组成

  具体来讲,扩展后的ASCII码表可以看成由三部分组成:

  第一部分:由00H到1FH共32个,一般用来通讯或作为控制之用。有些可以显示在屏幕上,有些则不能显示,但能看到其效果(如换行、退格)

  第二部分:是由20H到7FH共96个,这95个字符是用来表示阿拉伯数字、英文字母大小写和下划线、括号等符号,都可以显示在屏幕上.

  第三部分:由80H到0FFH共128个字符,一般称为"扩充字符",这128个扩充字符是由IBM制定的,并非标准的ASCII码.这些字符是用来表示框线、音标和其它欧洲非英语系的字母。

 

ascii值     字符     unicode
128    Ç     0xc7
129    ü     0xfc
130    é     0xe9
131    â     0xe2
132    ä     0xe4
133    à     0xe0
134    å     0xe5
135    ç     0xe7
136    ê     0xea
137    ë     0xeb
138    è     0xe8
139    ï     0xef
140    î     0xee
141    ì     0xec
142    Ä     0xc4
143    Å     0xc5
144    É     0xc9
145    æ     0xe6
146    Æ     0xc6
147    ô     0xf4
148    ö     0xf6
149    ò     0xf2
150    û     0xfb
151    ù     0xf9
152    ÿ     0xff
153    Ö     0xd6
154    Ü     0xdc
155    ¢     0xa2
156    £     0xa3
157    ¥     0xa5
158    ₧     0x20a7
159    ƒ     0x192
160    á     0xe1
161    í     0xed
162    ó     0xf3
163    ú     0xfa
164    ñ     0xf1
165    Ñ     0xd1
166    ª     0xaa
167    º     0xba
168    ¿     0xbf
169    ⌐     0x2310
170    ¬     0xac
171    ½     0xbd
172    ¼     0xbc
173    ¡     0xa1
174    «     0xab
175    »     0xbb
176    ░     0x2591
177    ▒     0x2592
178    ▓     0x2593
179    │     0x2502
180    ┤     0x2524
181    ╡     0x2561
182    ╢     0x2562
183    ╖     0x2556
184    ╕     0x2555
185    ╣     0x2563
186    ║     0x2551
187    ╗     0x2557
188    ╝     0x255d
189    ╜     0x255c
190    ╛     0x255b
191    ┐     0x2510
192    └     0x2514
193    ┴     0x2534
194    ┬     0x252c
195    ├     0x251c
196    ─     0x2500
197    ┼     0x253c
198    ╞     0x255e
199    ╟     0x255f
200    ╚     0x255a
201    ╔     0x2554
202    ╩     0x2569
203    ╦     0x2566
204    ╠     0x2560
205    ═     0x2550
206    ╬     0x256c
207    ╧     0x2567
208    ╨     0x2568
209    ╤     0x2564
210    ╥     0x2565
211    ╙     0x2559
212    ╘     0x2558
213    ╒     0x2552
214    ╓     0x2553
215    ╫     0x256b
216    ╪     0x256a
217    ┘     0x2518
218    ┌     0x250c
219    █     0x2588
220    ▄     0x2584
221    ▌     0x258c
222    ▐     0x2590
223    ▀     0x2580
224    α     0x3b1
225    ß     0xdf
226    Γ     0x393
227    π     0x3c0
228    Σ     0x3a3
229    σ     0x3c3
230    µ     0xb5
231    τ     0x3c4
232    Φ     0x3a6
233    Θ     0x398
234    Ω     0x3a9
235    δ     0x3b4
236    ∞     0x221e
237    φ     0x3c6
238    ε     0x3b5
239    ∩     0x2229
240    ≡     0x2261
241    ±     0xb1
242    ≥     0x2265
243    ≤     0x2264
244    ⌠     0x2320
245    ⌡     0x2321
246    ÷     0xf7
247    ≈     0x2248
248    °     0xb0
249    ∙     0x2219
250    ·     0xb7
251    √     0x221a
252    ⁿ     0x207f
253    ²     0xb2
254    ■     0x25a0
255    ÿ     0xff
扩展ASCII编码对照表

2.3 ISO-8859

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

  不过 ISO-8859 不是一个字符集,而是一系列扩充的ASCII码字符集。

Unicode 编号(二进制) 01001110 11100110 00101110 11101100 Unicode 编号(十六进制) 4E E6 
 2E EC UTF-8 编码(二进制) 01001110 11000011 10100110 11100010 10111011 10101100 UTF-8 编码(十六进制) 4E C3 A6 E2 BB AC

  UTF-8编码的最大长度是6个字节。

  对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同,用1个字节表示,首位为0。

  对于0x80-0x7FF之间的字符,用2个字节表示,第一个字节前三位“110”为标志位,第二个字节前两位“10”为标志位。剩下的11位用来表示Unicode值(7FF最多11位)。

  同样,UTF-8的3个字节,可以表示0x800-0xFFFF的Unicode(最多16位)。

  UTF-8的4个字节,可以表示0x10000-0x001FFFFF的Unicode(最多21位)。

  4个字节以内,已经包含了Unicode所有字符。

  5、6个字节表示的已经是非Unicode编码范围,属于UCS-4 编码。早期UTF-8规范也可以达到6字节序列,不过2003年11月UTF-8 被 RFC 3629 重新规范,只能使用原来Unicode定义的区域, U+0000到U+10FFFF。根据规范,这些字节值将无法出现在合法 UTF-8序列中。

  例:“汉”字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
  例2:Unicode编码0x20C30在0x010000-0x10FFFF之间,使用用4字节模板了:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。将0x20C30写成21位二进制数字(不足21位就在前面补0):0 0010 0000 1100 0011 0000,用这个比特流依次代替模板中的x,得到:11110000 10100000 10110000 10110000,即F0 A0 B0 B0。

  UTF-8有两个好处:

  1. 1字节字符、2字节字符、3字节字符……的首字节标志位不同,这样可以很清楚的区分一个字节属于1字节字符还是2字节字符,如果一个字节流传输中出现错误,也不会错位,只影响部分字符,根据标志位,很容易找到下个正确字符。

  2. 兼容ASCII码,英美字符用UTF-8可以一个字节表示,所以,www组织选用UTF-8作为推荐编码格式。2007年,在互联网上,UTF-8格式已经超过了ASCII码。

 

2.9 UTF-16

  UTF-16以2字节为单位,等同于UCS-2.

Unicode编码(十六进制 
UTF-16 字节流(二进制)
00000000 - 0000FFFF
xxxxxxxx xxxxxxxx
00010000 - 0010FFFF
110110yyyyyyyyyy 110111xxxxxxxxxx

   Unicode值小于等于0xFFFF的,直接用两个字节表示,超过0xFFFF的,无法用两个字节表示。使用下面公式编码:

1. 计算 U’= U – 0x10000

2. 将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx

3. 加上标志位,1101 10yy yyyy yyyy 1101 11xx xxxx xxxx

  可见,这是4个字节表示,2个6位标志位,20位有效位。因为U最大是0x10FFFF,所以U’最大是0xFFFFF,20位足够表示。

  windows上默认的Unicode编码方式就是UTF-16,使用wchar_t表示。

2.10 UTF-32

  UTF-32编码以4字节为单位。直接把Unicode值转为4字节二进制数就是其UTF-32编码。等同于UCS-4.

2.11 Base64

有的电子邮件系统(比如国外信箱)不支持非英文字母(比如汉字)传输,这是历史原因造成的(认为只有美国会使用电子邮件?)。因为一个英文字母使用ASCII编码来存储,占存储器的1个字节(8位),实际上只用了7位2进制来存储,第一位并没有使用,设置为0,所以,这样的系统认为凡是第一位是1的字节都是错误的。而有的编码方案(比如GB2312)不但使用多个字节编码一个字符,并且第一位经常是1,于是邮件系统就把1换成0,这样收到邮件的人就会发现邮件乱码。
为了能让邮件系统正常的收发信件,就需要把由其他编码存储的符号转换成ASCII码来传输。比如,在一端发送GB2312编码->根据Base64规则->转换成ASCII码,接收端收到ASCII码->根据Base64规则->还原到GB2312编码
 

2.12 Big5

  在台湾、香港与澳门地区,使用的是繁体中文字符集。而1980年发布的GB2312面向简体中文字符集,并不支持繁体汉字。在这些使用繁体中文字符集的地区,一度出现过很多不同厂商提出的字符集编码,这些编码彼此互不兼容,造成了信息交流的困难。为统一繁体字符集编码,1984年,台湾五大厂商宏碁、神通、佳佳、零壹以及大众一同制定了一种繁体中文编码方案,因其来源被称为五大码,英文写作Big5,后来按英文翻译回汉字后,普遍被称为大五码。
  大五码是一种繁体中文汉字字符集,其中繁体汉字13053个,808个标点符号、希腊字母及特殊符号。大五码的编码码表直接针对存储而设计,每个字符统一使用两个字节存储表示。第1字节范围81H-FEH,避开了同ASCII码的冲突,第2字节范围是40H-7EH和A1H-FEH。因为Big5的字符编码范围同GB2312字符的存储码范围存在冲突,所以在同一正文不能对两种字符集的字符同时支持。
  Big5编码的分布如表1-5所示,Big5字符主要部分集中在三个段内:标点符号、希腊字母及特殊符号;常用汉字;非常用汉字。其余部分保留给其他厂商支持。
编码范围
符号类别
8140H-A0FEH
保留(用作造字区)
A140H-A3BFH
标点符号、希腊字母及特殊符号
A3C0H-A3FEH
保留(未开放用于造字区)
A440H-C67EH
常用汉字 (先按笔划,再按部首排序)
C6A1H-C8FEH
保留(用作造字区)
C940H-F9D5H
非常用汉字(先按笔划,再按部首排序)
F9D6H-FEFEH
保留(用作造字区)
  Big5编码推出后,得到了繁体中文软件厂商的广泛支持,在使用繁体汉字的地区迅速普及使用。目前,Big5编码在台湾、香港、澳门及其他海外华人中普遍使用,成为了繁体中文编码的事实标准。在互联网中检索繁体中文网站,所打开的网页中,大多都是通过Big5编码产生的文档。
 

3 各种字符编码之间的关系

 上面关于字符集和编码讲了许多概念,其实归类一下可以这么理解:

 首先是单字节字符集:

    1、最初美国ANSI发明了自己的编码ASCII7-bit足够,这是标准ASCII

    2、标准ASCII码没有西欧国家拉丁文、英镑等字符,各公司、国家开始扩展,形成自己的扩展ASCII码字符集,各方混战,不过8-bit也就足够。

    3、天下分久必合,ISO统一了8-bit字符集,叫做ISO 8859.

但是亚洲国家字符更多,一个字节远远不够,于是用多个字节表示,扩展形成本国字符集,中国GB系列,台湾Big5,日本JIS……,这些叫做多字节字符集(MBCS),windows中用双字节表示,也叫做(DBCS

以上字符都是群雄割据,各自为政,windows为了迎合大家需求,在哪个国家,默认编码就用那个国家的,不过后来不知怎么被误传位ANSI编码,其实ANSI怎么可能定义世界各国编码,不过可以理解成各编码都是在ANSI基础上扩展的,因为都兼容ANSI的标准ASCII码。

这时,ISO再次出手,和Unicode联盟携手打造了UnicodeUCS),意图一统江湖。Unicode确实包罗万象,涵盖了各国字符,于是流行世界。Unicode自身只定义了每个字符的数值,真正二进制编码格式却是UTF-8UTF-16UCS-2),UTF-32UCS-4)。

至此,天下一统,但愿程序员的太平盛世到来了!

 

参考文章

字符集和字符编码notbecoder

字符编码的概念(UTF-8、UTF-16、UTF-32都是什么鬼) ,   严长生.

字符编码,百度百科,2018.12。

 ASCII,百度百科,2018.12.

 ASCII码表及扩展ASCII码表松下一田

计算机编码--2.ASCII与ANSI、ASCII扩展与IOS-8859-1今夕何夕_19882018.7。

 

 

没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。

永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧!

多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值