字符编码详解
字符编码详解
版本:v2.3.1
摘要
本文主要介绍了字符编码的*础知识,以及常见的字符编码类型,比如ASCII,Unicode,UTF-8,ISO 8859等,以及各种编码之间的关系,同时专门解释了中文字符相关的编码标准,包括GB2312,GBK,GB18030,也专门解释了Windows系统中的Code Page,以及相关的BOM等内容
2.5. 代码页Code Page
Code Page,是字符编码的另一种说法。
Code Page包含了一个表,表中的值,用于表示针对某种语言所用的字符集。
更简单点说,就是Code Page中,用一个数字编号,表示了所要采用何种字符编码,去编解码相应的值,用于正确显示出相应的字符。
Code Page这一概念,源于IBM,后被其他常见广泛采用,包括Microsoft,SAP,Oracle等。
这些常见,各自定义了一套自己的Code Page,给每一个code page号,指定一个字符编码。
比如,对于众所周知的UTF-8编码,在IBM的Code Page中编号是1208,在微软中是65001,在SAP中是4110。
接下来,主要介绍大家最常见的Windows的Code Page
如前所述,Windows中也有自己的一套Code Page的定义。
用对应的某个数字,Code Page Number,即Code Page中的标识符(Identifier),表示相应的字符编码。
而一般Code Page也常缩写为CP
比如,CP936表示GBK中文编码,CP65001表示UTF-8编码,CP54936表示GB18030编码,CP950表示BIG5繁体中文等等。
Windows中的Code Page,按照引用领域来划分,可以分为两类:ANSI Code Page和 OEM Code Page
ANSI Code Page的官网正式叫法其实是Windows Code Page。但是由于ANSI Code Page被误用的太广泛了,索性微软也就接受了此叫法,然后就叫做ANSI Code Page了。
类似地,ANSI Code Page=ANSI Windows Code Page
ANSI Code Page主要是用于Windows系统中,本地编码是非Unicode的,图形用户界面(GUI)程序。
ANSI的Code Page相关的表格,参见第 A.3.1.1 节 “ANSI Code Page表”
OEM Code Page主要是用于Windows系统中的命令行界面(console)程序,虚拟DOS。
OEM Code Page可以视为是DOS和IBM PC时代的(过渡)剩余产品。
除了ANSI Code Page之外,之所以又设计出一个OEM Code Page,是因为:
- 兼容性
因为作为新的图形用户界面系统的Windows,也要兼容旧的命令行程序,即向后兼容性。
- 字体和硬件的要求
字体和旧的VGA硬件建议,文字图形界面所用的编码,最好和Code Page 437兼容。
多数的OEM的Code Page,和(非ASCII的)后半部分的CP437,都是公用同一套代码点(code point)的。
一般的OEM Code Page的后半段编码,和ANSI Code Page,完全不同。不过,对于部分双字节编码的,定长的Code Page(如泰语的847,越南语的1258)和多字节CJK编码的Code Page(如932,936,949,950)来说,ANSI和OEM的Code Page,都用的同一套编码。
和OEM Code Page相关的表格,参见第 A.3.1.2 节 “OEM Code Page表”
其中,ANSI和OEM共有的一些Code Page,可参见第 A.3.1.3 节 “ANSI和OEM共有的Code Page表”
而其他一些常见的Code Page,可参见第 A.3.1.4 节 “其他一些常见的Code Page表”
除了ANSI和OEM,以及ANSI,OEM共有的Code Page之外,其他还有很多Code Page定义。
关于所有的Windows中的Code Page的定义,可在微软官网[21]中找到。
此处已收录至第 A.3.2 节 “所有的Code Page相关的表格”,以方便查阅。
2.6. ANSI字符编码
ANSI,本身是American National Standards Institute的缩写,中文翻译为美国国家标准学会
ANSI是个非营利组织,其负责制定美国国家标准。
ANSI字符编码的规则,或者是其所包含的字符的由来,主要是:
- 0-127 (0x00-0x7F)
完全和7位编码的ASCII字符集(ASA X3.4-1963)相同
- 128-159 (0x80-0x9F)
一些可打印字符
这部分的编码,与国际编码ISO 8859-1的做法不同,ISO 8859-1是将此部分编码用于控制字符
- 160-255 (0xA0-0FF)
参考了ISO 8859-1中的字符
由此可以看出,ANSI中很多字符,和ISO-8859中的字符,看起来非常相似。
这就导致了很多人误以为,ANSI和ISO-8859是一回事呢。
总结:
ANSI
= Windows Code Page 1252
= Windows Codepage 1252
= Windows 1252
= CP 1252
= 共256个字符
= 0-127的ASCII + 128-159的可打印字符 + 160-255的和ISO 8859-1中类似的字符
既然ANSI负责制定美国的国标,而在计算机方面,由于计算机最早是从美国最开始发展的,相应的所用到的字符编码方面,ANSI也制定了对应的标准,所以就叫做ANSI字符编码/ANSI字符集,英文为ANSI Code/ANSI Encoding/ANSI set/ANSI charset
Windows为了支持英语和西欧字符,自己设计了一个编码,对应的在Code Page号是1252,被称为Windows 1252。
Windows 1252的设计,是参考了ANSI草案(ANSI Draft)。
而ANSI draft后来发展成为正式的国际标准:ISO 8859-1
即,Windows 1252是在其成为正式标准ISO 8859-1之前而设计的,因此很容易理解,Windows 1252和ISO 8859-1不是完全等同的。
下面就来简要说说两者的区别。
Windows 1252和ISO 8859-1*本等同
有点不同的是,在128-159(0x80-0x9F)的范围的值,ISO 8859-1编码为控制字符,而微软编码为可打印字符。
![]() |
Windows 1252 vs. ANSI |
---|---|
|
总之,对于Windows 1252,目前的各种叫法,可以理解为:
ANSI = Windows 1252 = CP 1252 = Windows code page 1252 = Windows Latin-1
先说一下本地编码,所谓本地编码,即当前Windows中的二进制的值,用何种编码去解析,然后显示出对应的该编码中的字符。
即,当然系统使用什么类型的编码。
而ANSI编码,根据前面内容得知,只是一个普通的对应于Windows 1252的一个编码而已。并不是其他某些编码合集的总称。
但是有时候,却又看到有人把ANSI编码解释为“本地编码”,比如[19]
其意思,就是[27]中所说的,Windows code pages有时又被称为"active code pages","system active code pages"。
而作为微软用A表示ANSI版本的函数,W表示Wide,Unicode版本的函数,此时所有的A版本的函数,就都用的是当前有效的Code Page,即"本地编码"了
其中,Windows系统中,当前有且只有一个active Windows code page。
也就意味着,此处所谓的ANSI编码,就相当于之前所说的Code Page了,即当前系统采用何种编码去解析字符
也就是你当前系统中设置的本地编码为何种编码,然后系统中,遇到需要解析的字符,就按照你所设置的本地编码去解析了。
比如,本身对于中文GBK编码的字符,如果你本地编码设置为UTF-8,那么按照UTF-8编码去解析出来的GBK字符,当前就是乱码了。
而只有正确设置为GBK,才能正确解析原本就是GBK编码后的字符,才能正确显示出中文。
同理,用GBK编码去解析原本用UTF-8编码后的字符,也会导致乱码。
![]() |
提示 |
---|---|
这种乱码问题,常常会在和编码打交道的事情中遇到 比如Python中在命令行cmd中打印输出字符串,如果本身字符串是GBK编码的,那么你的cmd中的本地编码,就要设置为是936 (ANSI/OEM - Simplified Chinese GBK),这样中文字符才能正确显示。 当然,如果你本身输出的字符中,即包含UTF-8编码的字符,又包含GBK编码的字符,那么则是无论如何设置,都是无法同时正常显示的。除非你转换为Unicode编码,然后让Python输出函数自动处理,才可以正确显示。 |
2.8. 中文字符编码标准
1980年,中国制定了GB2312-80,一共收录了 7445 个字符,包括 6763 个汉字和 682 个其它符号。
GB2312-80,简称为GB2312。
在 Windows 中的代码页(Code Page)是 CP936。
1993年,国际标准Unicode 1.1版本推出,收录中国大陆、台湾、日本及韩国通用字符集的汉字,总共有20,902个。
中国大陆订定了等同于Unicode 1.1版本的“GB 13000.1-93”,简称为GB13000。
GB13000,显然包含的GB2312已有的文字和其他很多为包含的文字,如GB 2312-80推出以后才简化的汉字(如“啰”),部分人名用字(如中国前总理***的“*”字),台湾及香港使用的繁体字,日语及朝鲜语汉字等。
微软,对GB2312-80的扩展,即利用GB 2312-80未使用的编码空间,收录所有的GB 13000.1-93和Unicode 1.1之中的汉字全部字符,制定了GBK编码。
GBK 收录了 21886 个符号,它分为汉字区和图形符号区。汉字区包括 21003 个字符。
GBK 作为对 GB2312 的扩展,在现在的 Windows 系统中仍然使用代码页 CP936 表示,但是同样的 936 的代码页跟一开始的 936 的代码页只支持 GB2312 编码不同,现在的 936 代码页支持 GBK 的编码,GBK 同时也向下兼容GB2312 编码。
所以,技术编码上,GBK兼容旧的GB2312,但是编码方式和GB13000不同,不兼容GB13000,但是所包含文字上,算是和GB13000相同。
GBK自身并非国家标准,只是曾由国家技术监督局标准化司、电子工业部科技与质量监督司公布为“技术规范指导性文件”。
原始GB13000一直未被业界采用,2000年,国家出了标准GB18030-2000,简称GB18030,技术上兼容GBK而非GB13000,取代了 GBK1.0,成了正式的国家标准。
该标准收录了 27484 个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。
现在的PC平台必须支持 GB18030 ,对嵌入式产品暂不作要求。所以手机、MP3 一般只支持 GB2312。
GB18030 在 Windows 中的代码页是 CP54936。
这么多汉字编码标准的关系,总结起来就是第 2.8.2 节 “各种中文字符编码标准的关系”中所介绍的。
( 中国大陆的标准)GB 13000.1-93
=(国际标准)Unicode 1.1
(中国大陆标准)GB2312-80
= 简称GB2312
= Windows系统中的原先的CP936
(微软制定的)GBK
= (微软在编码方面)对 GB2312 的扩展
= (微软在所包含字符方面上包含了)GB 13000.1-93 + 其他部分汉字+ 台湾和香港的繁体 + 日语 + 朝鲜汉字
= Unicode 1.1 + 其他部分汉字+ 台湾和香港的繁体 + 日语 + 朝鲜汉字
对于GBK:
- 在编码方面:向下兼容GB2312,但是和GB 13000不同
- 在内容方面:等价于GB13000
微软中现在的新的CP936
= GBK
=兼容旧的GB2312
在技术编码方面上,演化顺序为:
ASCII ⇒ GB2312 ⇒ GBK ⇒ GB18030
后者对之前的,都是支持之前的编码,即向下兼容,即同一个字符,在这些编码中,都是同样的值,后面的标准,支持更多的字符。
区分中文编码的方法是高字节的最高位不为 0。
按照程序员的称呼,GB2312、GBK 到 GB18030 都属于双字节字符集 (DBCS)
作者:Chuck Lu GitHub |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2020-05-21 领域驱动设计DDD
2020-05-21 如何退出telnet
2019-05-21 vs 2019 create new project 创建新项目
2019-05-21 Aspect-Oriented Programming : Aspect-Oriented Programming with the RealProxy Class
2019-05-21 Aspect-oriented programming
2019-05-21 Gitblit用户没有push权限,但是已经在team里面配置了
2018-05-21 第三章 基本概念