字符编码
字符编码,近年来一直困扰着我,感觉平常遇到的UTF-8,GBK,Unicode,ANSI等编码大致知道意思也就可以了,没有必要去给它一个细分。
但是,今天发现不得不去好好梳理一下他们的关系了。因为这个地方老是出些莫名其妙的问题。
1. 字符集和字符编码
首先明确两个概念,“字符集”(charset)和“字符编码”(encoding)。有些地方经常把这两个概念等同,比如说到ASCII码,有时候指“字符集”,有时候指“字符编码”,其实这是两个不同的概念,混淆了这两个概念,很难真正理解一些概念,比如Unicode和Utf8、Utf16的关系(其实Unicode是字符集和第一层字符编码,Utf8、Utf16是第二层字符编码,它们都表示了同一个字符集)。
字符集顾名思义是“许多字符的集合”,这些字符组成一套符号系统,可以组合起来形象的表达各种含义。比如26个英文字母加上标点符号可以组成“英文字符集”,这个字符集的组合可以形成英美人可以理解的一套文字系统,看到了“I love you”,就能明白什么意思。再比如新华字典中的所有汉字加上标点符号可以组成“中文字符集”,这个字符集的组合可以形成中文文字系统,看到“我爱你”就能理解其含义。对于老外,如果不懂中文,看到“我爱你”三个字符,可能以为就是“鬼画符”。
“字符编码”字面意思就是“对字符进行编码”。呵呵,听起来有点废话。那先说下为什么要对字符进行编码。对字符编码的最大目的还是为了传输、储存信息(其实储存也是为了传输,是为了能传给以后的人看)。
字符编码的四个步骤
从上一节来看,“字符集”是一种形象表意的工具,“字符编码”是表示字符的一种方式。在计算机出现之前就已经有了这两种技术。计算机中,是使用二进制的方式对字符集重新编码。
在计算机中,要建立一种“字符编码模型”,需要四步:
- 要有一个字符库,确定这些字符足够表意。 比如ASCII字符集,已经足够表示英语,但不能表示中文,于是产生GB2312字符集。
- 第一层编码,给每个字符编个数字,英文叫Code Point 或 Code Position。比如ASCII字符集中,65表示“A”,97表示“a”。
- 第二层编码,确定表示字符的二进制位数(8位,16位,32位)。ASCII使用7位,DBCS(双字节字符集)使用16位。
- 第三层编码,确定字符二进制值的存储格式(大端法,小端法)。比如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码字符集(比如,ATASCII,PETSCII等)。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码字符集。
字符编码,近年来一直困扰着我,感觉平常遇到的UTF-8,GBK,Unicode,ANSI等编码大致知道意思也就可以了,没有必要去给它一个细分。
但是,今天发现不得不去好好梳理一下他们的关系了。因为这个地方老是出些莫名其妙的问题。
1. 字符集和字符编码
首先明确两个概念,“字符集”(charset)和“字符编码”(encoding)。有些地方经常把这两个概念等同,比如说到ASCII码,有时候指“字符集”,有时候指“字符编码”,其实这是两个不同的概念,混淆了这两个概念,很难真正理解一些概念,比如Unicode和Utf8、Utf16的关系(其实Unicode是字符集和第一层字符编码,Utf8、Utf16是第二层字符编码,它们都表示了同一个字符集)。
字符集顾名思义是“许多字符的集合”,这些字符组成一套符号系统,可以组合起来形象的表达各种含义。比如26个英文字母加上标点符号可以组成“英文字符集”,这个字符集的组合可以形成英美人可以理解的一套文字系统,看到了“I love you”,就能明白什么意思。再比如新华字典中的所有汉字加上标点符号可以组成“中文字符集”,这个字符集的组合可以形成中文文字系统,看到“我爱你”就能理解其含义。对于老外,如果不懂中文,看到“我爱你”三个字符,可能以为就是“鬼画符”。
“字符编码”字面意思就是“对字符进行编码”。呵呵,听起来有点废话。那先说下为什么要对字符进行编码。对字符编码的最大目的还是为了传输、储存信息(其实储存也是为了传输,是为了能传给以后的人看)。
字符编码的四个步骤
从上一节来看,“字符集”是一种形象表意的工具,“字符编码”是表示字符的一种方式。在计算机出现之前就已经有了这两种技术。计算机中,是使用二进制的方式对字符集重新编码。
在计算机中,要建立一种“字符编码模型”,需要四步:
- 要有一个字符库,确定这些字符足够表意。 比如ASCII字符集,已经足够表示英语,但不能表示中文,于是产生GB2312字符集。
- 第一层编码,给每个字符编个数字,英文叫Code Point 或 Code Position。比如ASCII字符集中,65表示“A”,97表示“a”。
- 第二层编码,确定表示字符的二进制位数(8位,16位,32位)。ASCII使用7位,DBCS(双字节字符集)使用16位。
- 第三层编码,确定字符二进制值的存储格式(大端法,小端法)。比如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码字符集(比如,ATASCII,PETSCII等)。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)
看到没,早期有四个版本是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
2.3 ISO-8859
由于各公司、国家之间都有自己的字符集,同一个数值,在不同的字符集之间表示的符号可能不一样,这样在一台电脑上正常可以阅读的文件,到另外一台电脑可能就成了乱码。为了解决这个问题,ISO组织统一了一套标准字符集,就是ISO-8859.
不过 ISO-8859 不是一个字符集,而是一系列扩充的ASCII码字符集。