频道栏目
IT货架 > > 正文
字符编码详解
网友分享于:Jan 1, 1970 8:00:00 AM    来源: IT货架   

标签:des   style   blog   http   color   io   os   使用   ar   

字符编码详解

版本:v2.2

 

Crifan Li

摘要

本文主要介绍了字符编码的基础知识,以及常见的字符编码类型,比如ASCII,Unicode,UTF-8,ISO 8859等,以及各种编码之间的关系,同时专门解释了中文字符相关的编码标准,包括GB2312,GBK,GB18030,也专门解释了Windows系统中的Code Page,以及相关的BOM等内容

2012-08-09

修订历史
修订 1.0 2011-11-02 crl
  1. 添加了编码相关背景知识介绍
  2. 添加了ASCII和EASCII编码介绍
  3. 添加了ISO/IEC 8859相关的编码和各种单字节编码的关系
  4. 添加了Unicode和ISO 10646的解释
  5. 添加了UTF-8和Unicode的区别和联系
修订 2.2 2012-08-09 crl
  1. 通过Docbook发布
  2. 合并了原先在zhcn_charset中的内容
  3. 详细解释了Code Page
  4. 详细解释了ANSI编码
  5. 解释BOM

目录

缩略词
正文之前
1. 目的
2. 本文内容
3. 声明
1. 字符编码相关的背景知识
1.1. 拉丁字母
1.1.1. 我们的目标
1.2. 什么是字符编码
2. 字符编码标准
2.1. 只支持基本的拉丁字符的字符编码:ASCII
2.1.1. ASCII的由来
2.1.2. ASCII编码规则
2.1.2.1. ASCII字符集中的功能/控制字符
2.1.2.1.1. 什么是Function Code功能码或 Function Character功能字符
2.1.2.1.2. ASCII中的Function/Control Code功能字符的详细含义
2.1.2.1.2.1. 0 – NUL – NULl 字符/空字符
2.1.2.1.2.2. 1 – SOH – Start Of Heading 标题开始
2.1.2.1.2.3. 2 – STX,3 – ETX
2.1.2.1.2.4. 4 – EOT – End Of Transmission 传输结束
2.1.2.1.2.5. 5 – ENQ – ENQuiry 请求
2.1.2.1.2.6. 6 – ACK – ACKnowledgment 回应/响应
2.1.2.1.2.7. 7 – BEL – [audible] BELl
2.1.2.1.2.8. 8 – BS – BackSpace 退格键
2.1.2.1.2.9. 9 – HT – Horizontal Tab 水平制表符
2.1.2.1.2.10. 10 – LF – Line Feed 换行
2.1.2.1.2.11. 11 – VT – Vertical Tab 垂直制表符
2.1.2.1.2.12. 12 – FF – Form Feed 换页
2.1.2.1.2.13. 13 – CR – Carriage return 机器的滑动部分/底座 返回 -> 回车
2.1.2.1.2.14. 14 – SO,15 – SI
2.1.2.1.2.15. 16 – DLE – Data Link Escape 数据链路转义
2.1.2.1.2.16. 17 – DC1 – Device Control 1 / XON – Transmission on
2.1.2.1.2.17. 18 – DC2 – Device Control 2
2.1.2.1.2.18. 19 – DC3 – Device Control 3 / XOFF – Transmission off 传输中断
2.1.2.1.2.19. 20 – DC4 – Device Control 4
2.1.2.1.2.20. 21 – NAK – Negative AcKnowledgment 负面响应-> 无响应, 非正常响应
2.1.2.1.2.21. 22 – SYN – SYNchronous idle
2.1.2.1.2.22. 23 – ETB – End of Transmission Block 块传输中止
2.1.2.1.2.23. 24 – CAN – CANcel 取消
2.1.2.1.2.24. 25 – EM – End of Medium 已到介质末端,介质存储已满
2.1.2.1.2.25. 26 – SUB – SUBstitute character替补/替换
2.1.2.1.2.26. 27 – ESC – ESCape 逃离/取消
2.1.2.1.2.27. 28 – FS – File Separator 文件分隔符
2.1.2.1.2.28. 29 – GS – Group Separator分组符
2.1.2.1.2.29. 30 – RS – Record Separator记录分隔符
2.1.2.1.2.30. 31 – US – Unit Separator 单元分隔符
2.1.2.1.2.31. 32 – SP – White SPace 空格键
2.1.2.1.2.32. 127 – DEL – DELete 删除
2.1.2.1.3. 各种字符的标准的读法/叫法
2.1.3. ISO 646
2.2. 支持多种衍生拉丁字母的字符编码:EASCII和ISO 8859
2.2.1. EASCII
2.2.2. ISO 8859
2.2.2.1. ISO/IEC 8859出现的背景
2.2.2.2. ISO/IEC 8859的编码规则
2.2.2.3. ISO/IEC 8859的特点
2.2.2.4. ISO/IEC 6429
2.2.2.5. ISO 8859和ISO-8859的区别和联系
2.2.2.5.1. 原先的ISO 8859-1和我们常说的ISO 8859-1
2.3. 各种单字节编码标准的关系
2.4. 支持世界上几乎所有字符的字符编码:Unicode
2.4.1. Unicode和ISO 10646的关系
2.4.1.1. ISO 10646=UCS
2.4.1.2. Unicode 和ISO 10646的联系
2.4.1.3. Unicode和ISO 10646的区别
2.4.2. Unicode编码规则
2.4.3. Unicode字符编码所对应的存储和交换标准:UTF-8, UTF-16, UTF-32
2.4.3.1. UTF-8
2.4.3.2. Unicode与UTF-8之间的转换
2.4.3.2.1. 关于UTF-8的BOM:“EF BB BF”
2.5. 代码页Code Page
2.5.1. 什么是代码页(Code Page)
2.5.2. Windows中的Code Page
2.5.2.1. Windows中的Code Page分类:ANSI和OEM
2.5.2.1.1. Windows的ANSI Code Page表
2.5.2.1.2. Windows的OEM Code Page表
2.5.2.1.3. 一些常见的Code Page表
2.5.2.2. 所有的Code Page表
2.6. ANSI字符编码
2.6.1. ANSI是啥
2.6.2. ANSI编码规则
2.6.3. ANSI (Windows 1252)编码表
2.6.4. ANSI编码与ANSI的关系
2.6.5. ANSI字符编码和Windows 1252
2.6.5.1. Windows 1252和ISO 8859-1之间的区别
2.6.6. 为何"ANSI编码"(在Windows中)被称为"本地编码"
2.7. BOM
2.7.1. BOM是什么
2.7.2. 为何需要BOM
2.7.3. BOM表
2.8. 中文字符编码标准
2.8.1. GB2312,CP936,GBK,GB18030,GB13000
2.8.1.1. GB2312
2.8.1.2. GB13000
2.8.1.3. GBK
2.8.1.4. GB18030
2.8.2. 各种中文字符编码标准的关系
2.9. 字符存储(交换)标准
2.10. 字形和你所看到的字符的关系
参考书目
A. 编码相关的表格
A.1. ASCII编码表(0-127)
A.2. ISO/IEC 8859编码标准中的15种字符集
A.3. Code Page表格
A.3.1. 常见的ANSI和OEM的Code Page的表格
A.3.1.1. ANSI Code Page表
A.3.1.2. OEM Code Page表
A.3.1.3. ANSI和OEM共有的Code Page表
A.3.1.4. 其他一些常见的Code Page表
A.3.2. 所有的Code Page相关的表格
A.4. 不同编码所用的BOM

在介绍计算机的字符编码知识前,先来说说这个拉丁字母,估计也会有人和我一样,对于拉丁字母和英文字母以及汉语拼音中的字母的关系,不是很清楚。

拉丁字母,也叫罗马字母,是当今世界上使用最广的字母系统。

拉丁字母,或者说基本的拉丁字母,就是你所常见的到的ABCD等26个英文字母。

原先是欧洲那边使用的,后来由于欧洲殖民主义,导致后来的美洲等地,也是用的这套字母体系。

而其他有些地方,比如越南等,本来有自己的文字语言的,结果受西方文化的影响和由于基督教的传播,也用拉丁字母了。

所以总的说,现在欧洲多数国家,美洲,澳洲,非洲的多数国家,都是用的拉丁字母,即你所常见的英文字母,也是拉丁字母。而中国的汉语拼音,也是用的这个拉丁字母。

其中,欧洲很多国家,是对已有的26个基本的拉丁字母,加上连字,变音字符,弄出个衍生拉丁字母,但是还是属于拉丁字母。

说了这么多,就是要让你知道,后面内容所提到的英文字母,其来源于拉丁字母,而且我们汉语的汉语拼音,也是拉丁字母。

即:

  • 基本的拉丁字母 = 26个英文字母 = 汉语中的汉语拼音
  • 衍生的拉丁字母 = 从基本的26个英文字母,加上连字,变音等字符而衍生出来的拉丁字母 = 很多西欧国家的字母 (每个国家都不太一样)

计算机中存放的都是0和1的二进制值。8个位对应一个字节,常用16进制来表示。

而我们普通用户所希望看到的是,计算机把其所存储的对应的16进制的数值,转化为对应的字符,包括英文和中文等其他语言的字符,然后输出到屏幕上。

而所谓编码,就是,定义了一套规则,去指定,哪些数值,对应着哪些字符。

举个最简单的例子,常见65=0x41对应的是大写字母A,97=0x61对应的是小写字母a,而这套数值和字母之间的映射关系,说白了,就是一套规则,就叫做字符编码,即我们常说的ASCII编码。

那有人会问了,如果我定义了一套规则,假如叫张三编码,然后故意去把ASCII中的映射关系改变,比如97=0x61对应的是大写字母A,65=0x41对应的是小写字母a,等等,可不可以?答案是,完全可以,不过这套规则,首先没有得到所有计算机业界的一致认同,所以,除了你自己用,其他人不原意使用,那么也就是没了存在的价值了。

换句话说,当初ASCII之所以这么定义这套规则,就是这么定义了而已,然后大家都接受这个标准,然后就都用这个定义了。

即,如果当初定义为0x41代表的是小写字母a,而不是大写字母A,那么现在你所看到的,就是小写字母a就是对应着计算机中存储的0x41,而不是之前的0x61了。

所以,简单的说就是:

所谓字符编码,就是定义了一套规则,指定了计算机中存放的这么多值中的哪个值,对应了电脑屏幕显示出来的哪个字母。

目录

2.1. 只支持基本的拉丁字符的字符编码:ASCII
2.1.1. ASCII的由来
2.1.2. ASCII编码规则
2.1.2.1. ASCII字符集中的功能/控制字符
2.1.2.1.1. 什么是Function Code功能码或 Function Character功能字符
2.1.2.1.2. ASCII中的Function/Control Code功能字符的详细含义
2.1.2.1.2.1. 0 – NUL – NULl 字符/空字符
2.1.2.1.2.2. 1 – SOH – Start Of Heading 标题开始
2.1.2.1.2.3. 2 – STX,3 – ETX
2.1.2.1.2.4. 4 – EOT – End Of Transmission 传输结束
2.1.2.1.2.5. 5 – ENQ – ENQuiry 请求
2.1.2.1.2.6. 6 – ACK – ACKnowledgment 回应/响应
2.1.2.1.2.7. 7 – BEL – [audible] BELl
2.1.2.1.2.8. 8 – BS – BackSpace 退格键
2.1.2.1.2.9. 9 – HT – Horizontal Tab 水平制表符
2.1.2.1.2.10. 10 – LF – Line Feed 换行
2.1.2.1.2.11. 11 – VT – Vertical Tab 垂直制表符
2.1.2.1.2.12. 12 – FF – Form Feed 换页
2.1.2.1.2.13. 13 – CR – Carriage return 机器的滑动部分/底座 返回 -> 回车
2.1.2.1.2.14. 14 – SO,15 – SI
2.1.2.1.2.15. 16 – DLE – Data Link Escape 数据链路转义
2.1.2.1.2.16. 17 – DC1 – Device Control 1 / XON – Transmission on
2.1.2.1.2.17. 18 – DC2 – Device Control 2
2.1.2.1.2.18. 19 – DC3 – Device Control 3 / XOFF – Transmission off 传输中断
2.1.2.1.2.19. 20 – DC4 – Device Control 4
2.1.2.1.2.20. 21 – NAK – Negative AcKnowledgment 负面响应-> 无响应, 非正常响应
2.1.2.1.2.21. 22 – SYN – SYNchronous idle
2.1.2.1.2.22. 23 – ETB – End of Transmission Block 块传输中止
2.1.2.1.2.23. 24 – CAN – CANcel 取消
2.1.2.1.2.24. 25 – EM – End of Medium 已到介质末端,介质存储已满
2.1.2.1.2.25. 26 – SUB – SUBstitute character替补/替换
2.1.2.1.2.26. 27 – ESC – ESCape 逃离/取消
2.1.2.1.2.27. 28 – FS – File Separator 文件分隔符
2.1.2.1.2.28. 29 – GS – Group Separator分组符
2.1.2.1.2.29. 30 – RS – Record Separator记录分隔符
2.1.2.1.2.30. 31 – US – Unit Separator 单元分隔符
2.1.2.1.2.31. 32 – SP – White SPace 空格键
2.1.2.1.2.32. 127 – DEL – DELete 删除
2.1.2.1.3. 各种字符的标准的读法/叫法
2.1.3. ISO 646
2.2. 支持多种衍生拉丁字母的字符编码:EASCII和ISO 8859
2.2.1. EASCII
2.2.2. ISO 8859
2.2.2.1. ISO/IEC 8859出现的背景
2.2.2.2. ISO/IEC 8859的编码规则
2.2.2.3. ISO/IEC 8859的特点
2.2.2.4. ISO/IEC 6429
2.2.2.5. ISO 8859和ISO-8859的区别和联系
2.2.2.5.1. 原先的ISO 8859-1和我们常说的ISO 8859-1
2.3. 各种单字节编码标准的关系
2.4. 支持世界上几乎所有字符的字符编码:Unicode
2.4.1. Unicode和ISO 10646的关系
2.4.1.1. ISO 10646=UCS
2.4.1.2. Unicode 和ISO 10646的联系
2.4.1.3. Unicode和ISO 10646的区别
2.4.2. Unicode编码规则
2.4.3. Unicode字符编码所对应的存储和交换标准:UTF-8, UTF-16, UTF-32
2.4.3.1. UTF-8
2.4.3.2. Unicode与UTF-8之间的转换
2.4.3.2.1. 关于UTF-8的BOM:“EF BB BF”
2.5. 代码页Code Page
2.5.1. 什么是代码页(Code Page)
2.5.2. Windows中的Code Page
2.5.2.1. Windows中的Code Page分类:ANSI和OEM
2.5.2.1.1. Windows的ANSI Code Page表
2.5.2.1.2. Windows的OEM Code Page表
2.5.2.1.3. 一些常见的Code Page表
2.5.2.2. 所有的Code Page表
2.6. ANSI字符编码
2.6.1. ANSI是啥
2.6.2. ANSI编码规则
2.6.3. ANSI (Windows 1252)编码表
2.6.4. ANSI编码与ANSI的关系
2.6.5. ANSI字符编码和Windows 1252
2.6.5.1. Windows 1252和ISO 8859-1之间的区别
2.6.6. 为何"ANSI编码"(在Windows中)被称为"本地编码"
2.7. BOM
2.7.1. BOM是什么
2.7.2. 为何需要BOM
2.7.3. BOM表
2.8. 中文字符编码标准
2.8.1. GB2312,CP936,GBK,GB18030,GB13000
2.8.1.1. GB2312
2.8.1.2. GB13000
2.8.1.3. GBK
2.8.1.4. GB18030
2.8.2. 各种中文字符编码标准的关系
2.9. 字符存储(交换)标准
2.10. 字形和你所看到的字符的关系

ASCII的编码规则,由于最初只是为英文字母所考虑的,而英文只有26个字母,以及加上其他大小写字母,常见的字符,常见数字等,所有的加起来,也就几十个,而一个字节8位中前7位的理论上可以表示27=128个字符,所以对于设计出来的编码规则来说,只需要用一个字节来表示,就足够了。

即ASCII编码规则中规定,用单个字节共8位来表示字符,其中最高位为0,其他7位所对于的每一个值,映射到某个特定的字符,这样就形成了ASCII编码。

ASCII共包含了27=128个字符。

其中包括33个不可显示的字符和95个可显示的字符。

而对于ASCII编码规则,简单说就是:

7位的字符编码,即每个字节的最高位第8位为0,其余7位的某个值对应着某个字符。

ASCII字符集共27=128个字符 = 33个控制字符 + 95个可见字符。

[提示] >ASCII中的可显示的字符和不可显示字符

ASCII中可显示的字符,也叫可打印printable字符;

而ASCII中的值为0 – 31的那些字符,叫做不可显示的字符,也叫不可见字符,不可打印(non-printable)字符,由于其字符的作用是起一定的控制作用,所以常称为控制字符(control character),即不同的字符实现不同的功能,因此又称为功能字符(function code,function character)。

即ASCII字符集中:

不可见字符

=不可打印(non-printable)字符

=控制字符(control character)

=功能字符(function code,function character)

对于ASCII中的控制字符,都包括哪些,以及每个字符的详细含义,第 2.1.2.1 节 “ASCII字符集中的功能/控制字符”中会有详细介绍。

ASCII字符集,大家都知道吧,最基本的包含了128个字符。其中前32个,0-31,即0x00-0x1F,都是不可见字符。这些字符,就叫做控制字符。

这些字符没法打印出来,但是每个字符,都对应着一个特殊的控制功能的字符,简称功能字符或功能码Function Code。

简言之:ASCII中前32个字符,统称为Function Code功能字符。

此外,由于ASCII中的127对应的是Delete,也是不可见的,所以,此处根据笔者的理解,也可以归为Function Code。

此类字符,对应不同的“功能”,起到一定的“控制作用”,所以,称为控制字符。

关于每个控制字符的控制功能缩写,参见表 2.1 “ASCII中的控制字符”

表 2.1. ASCII中的控制字符

十进制 十六进制 控制字符 转义字符1 说明 Ctrl + 下列字母2
0 00 NUL \0 Null character(空字符) @3
1 01 SOH   Start of Header(标题开始) A
2 02 STX   Start of Text(正文开始) B
3 03 ETX   End of Text(正文结束) C
4 04 EOT   End of Transmission(传输结束) D
5 05 ENQ   Enquiry(请求) E
6 06 ACK   Acknowledgment(收到通知/响应) F
7 07 BEL \a Bell(响铃) G
8 08 BS \b Backspace(退格) H
9 09 HT \t Horizontal Tab(水平制表符) I
10 0A LF \n Line feed(换行键) J
11 0B VT \v Vertical Tab(垂直制表符) K
12 0C FF \f Form feed(换页键) L
13 0D CR \r Carriage return(回车键) M
14 0E SO   Shift Out(不用切换) N
15 0F SI   Shift In(启用切换) O
16 10 DLE   Data Link Escape(数据链路转义) P
17 11 DC1   Device Control 1(设备控制1) /XON(Transmit On) Q
18 12 DC2   Device Control 2(设备控制2) R
19 13 DC3   Device Control 3(设备控制3) /XOFF(Transmit Off) S
20 14 DC4   Device Control 4(设备控制4) T
21 15 NAK   Negative Acknowledgement(拒绝接收/无响应) U
22 16 SYN   Synchronous Idle(同步空闲) V
23 17 ETB   End of Trans the Block(传输块结束) W
24 18 CAN   Cancel(取消) X
25 19 EM   End of Medium(已到介质末端/介质存储已满) Y
26 1A SUB   Substitute(替补/替换) Z
27 1B ESC \e Escape(溢出/逃离/取消) [
28 1C FS   File Separator(文件分割符) \
29 1D GS   Group Separator(分组符) ]
30 1E RS   Record Separator(记录分隔符) ^3
31 1F US   Unit Separator(单元分隔符) _3
32 20 SP   White space [Space]4
127 7F DEL   Delete(删除) ?5

1

即在C语言中或其他地方如何表示。

2

可以通过 “Ctrl+对应字母/按键”实现上述控制字符的输入

下面列举一些你可能遇到的情况:

3

注意此处想要在键盘上输入这三个字符的话,是需要通过Shift加上对应字符才能输入的:

  • @:用Shift + 2输入
  • ^:用Shift + 6输入
  • _:用Shift + -输入

4

32=0x20,对应的是空格(Blank Space)键。不需要加Ctrl键,即可直接通过键盘上的空格键输入。

5

127=0x7F=删除(Delete)键;,除了可以用键盘上的删除键输入,也可以用‘Ctrl+?‘输入。

2 – STX – Start Of Text 文本开始

3 – ETX – End Of Text 文本结束

通过某种通讯协议去传输的一个数据(包),称为一帧的话,常会包含一个帧头,包含了寻址信息,即你是要发给谁,要发送到目的地是哪里,其后跟着真正要发送的数据内容。

而STX,就用于标记这个数据内容的开始。接下来是要传输的数据,最后是ETX,表明数据的结束。

其中,中间具体传输的数据内容,ASCII规范并没有去定义,其和你所用的传输协议,具体自己要传什么数据有关。

帧头 数据或文本内容
SOH(表明帧头开始) ......(帧头信息,比如包含了目的地址,表明你发送给谁等等) STX(表明数据开始) ......(真正要传输的数据) ETX(表明数据结束

不过其中有趣的是,1963年,ASCII标准最初版本的时候,把现在的STX叫做EOA(End Of Address),ETX叫做(End Of Message)。

这是因为,最早的时候,一个消息中,总是包含一个开始符和一个终止符。现在的新的定义,使得可以去发送一个固定长度的命令,而只用一个SOH表明帧头开始即可,而不需要再加上一个命令终止符或帧头结束符。

总结一下:

一般发送一个消息,包含了一个帧头和后面真正要传的数据。

而对于帧头,属于控制类的信息,这部分之前属于命令,后面的真实要传的数据属于数据。即消息=帧头+数据。

而之前的命令都要有个开始符和结束符,这样就是:

消息

= 帧头 + 要传的数据

= 帧头开始+帧头信息+帧头结束 + 要传的数据

而现在新的定义,使得只需要:

消息

= 帧头 +要传的数据

= SOH(表明帧头开始)+帧头信息+ 要传的数据

= SOH(表明帧头开始)+帧头信息 + STX + 数据内容+ETX

就可以少用一个帧头结束符。

而如今,在很多协议中,也常见到,一个固定长度的帧头,后面紧接着就是数据了,而没有所谓的帧头结束符之类的东西去区分帧头和数据。

计算机出现之后,从美国发展到欧洲,而由于欧洲很多国家中所用到的字符中,除了基本的美国也用的那些拉丁字母之外,还有很多衍生的拉丁字母,而且是不同的国家用到的衍生字符都不太相同,所以欧洲人也遇到类似的问题,即如何将自己国家的那些字符,在计算机上显示出来,这就需要设计一个合理的字符编码,把所有这些字符都囊括其中。

即设计一个新编码标准,即兼容旧的ASCII的编码,又支持欧洲多个国家的那些衍生拉丁字母。

这样的标准有两个,一个是EASCII编码标准,一个是国际标准ISO 8859字符编码标准。

对于ISO/IEC 8859所包含的全部字符,我们可以看到,对于基本的拉丁字母,那都是和ASCII一样的,因为其就是借用了ASCII中的0x20-0x7F这段的编码,对应的是那些常见的可显示的字符,而对于0xA0-0xFF这段空间,则是对于同一个值,不同的字符集中,对应着不同的符号。

对于ISO/IEC 8859的编码方式是设计了多个字符集,我们不难看出,其之所以这么编码,而不是像ASCII中每个编码值,都对应唯一的一个字符,那是因为,欧洲的全部所用的字符数很多,如果是对于全部的欧洲用的字符都用一个对应的值来表示,那么这剩下的0xA0-0xFF,甚至是0x80-0xFF,也都不够用的,因为0x80-0xFF128个值,当然不够表示欧洲那几百上千的不同国家的不同字符。

所以,才会去设计出这么15个字符集,然后对于同一个值,你用了ISO/IEC 8859-n,就表示对应的字符集中的那个特定的字符。

而上述做法的好处是,可以避免去用多个字节,比如两个字节(8×2=16位,可以表示最多2^16=65536个字符)去表示一个单独的字符,即节省了存放数据的空间。

但是缺点是,比如你写一篇文章,中间出现了多个不同语系的不同的字符,那么此文章如果用ISO/IEC 8859来编码的话,那么就无法单独存成某一种对应的字符集,即包含多个欧洲国家不同语系的特殊字符的数据,无法用ISO/IEC 8859的某一个单独的字符集来表示出来,即无法在同一个文章中支持显示不同语系的不同的字符。

当然,相对于亚洲字符,即中文,日文,韩文等字符来说,另外一个如果算的上是缺点的话,那就是没有把咱亚洲字符考虑进去。

正因此,字符编码,才会继续演化出更加通用的,包含了世界上所有的字符的字符编码标准:Unicode。

关于Unicode的详细解释请去看:第 2.4 节 “支持世界上几乎所有字符的字符编码:Unicode”

此处先来说说,其他几个和ISO/IEC 8859相关的内容。

ISO 8859和ISO-8859,不是同一个东西。

注意,后者是ISO和8859中间带了一个小横短线的。

前者,ISO 8859是ISO/IEC 8859标准集合的简称,对应包含了 ISO/IEC 8859-n,其中n为除去2之外的1到16,这共15种字符集合。

ISO-8859,是ISO-8859-n的简称,是IANA根据ISO/IEC 8859-n的标准,加上对应的前面提到的普通的ASCII字符,和ISO/IEC 6429所定义的的控制字符,所制定的标准。

其中,由于ASCII中也包含了0x00-0x1F的控制字符,所以和ISO/IEC 6429中的C0控制字符重复了,但是两者定义都是一样的,所以从字符编码上来说,不会产生任何冲突。

因此,ISO-8859-n所以可以表示:

ISO-8859

= ISO-8859-n的简称

= ISO 8859-n + ASCII + ISO/IEC 6429

其中,n=1,...,11,13,...,16,共15种编码集合。

对应的,ISO 8859-1和ISO-8859-1两者当前也是不一样的,其区别也是:

 

ISO-8859-1

= ISO 8859-1 + ASCII + ISO/IEC 6429

= ISO/IEC 8859-1 + ASCII + ISO/IEC 6429

好了,介绍完了ISO/IEC 8859的种种,这下可以开始介绍Unicode了。

前面已经提到了,由于随着计算机的发展,自然会发展到亚洲各国和其他一些地方,然后这些国家也遇到同样问题,即如何把自己的国家的字符,显示到对应的屏幕上。

Unicode这个词的中文翻译,有译为万国码,单一码,标准万国码,但是最常见的翻译还是统一码。

为了将世界上几乎所有的字符都涵盖了,那么就要了解世界上,有哪些字符。

除了之前ASCII的拉丁字母,ISO 8859所包含的欧洲多国用的字符之外,亚洲一些国家,包括中文,日文,韩文等,尤其是中文,包含的字符数,大概有几万个。

因此,Unicode的编码就要设计的把这么多的字符都包含在内。

Unicode的编码方式与上面提到的ISO 10646的UCS概念相对应,目前实际应用的Unicode版本对应于UCS-2,即2字节的UCS字符集,使用16位的编码空间。每个字符占用2个字节,这样理论上一共最多可以表示2^16=65536个字符。基本满足各种语言的使用。实际上目前版本的Unicode尚未填充满这16位编码,保留了大量空间作为特殊使用或将来扩展。

上述16位Unicode字符构成基本多文种平面(Basic Multilingual Plane,简称BMP)。最新(但未实际广泛使用)的Unicode版本定义了16个辅助平面,两者合起来至少需要占据21位的编码空间,比3字节略少。但事实上辅助平面字符仍然占用4字节编码空间,与UCS-4保持一致。未来版本会扩充到ISO 10646-1实现级别3,即涵盖UCS-4的所有字符。

UCS-4是一个更大的尚未填充完全的31位字符集,加上恒为0的首位,共需占据32位,即4字节。理论上最多能表示2^31=2147483648=21亿左右个字符,完全可以涵盖一切语言所用的符号。

具体的取值范围和所对应的平面空间划分,参见图 2.3 “Unicode中的各种平面划分”


Unicode中的0-0xFFF的BMP中的任何一个编码的值,称为码点(Code Point),对应用U+hhhh来表示,其中每个h 代表一个十六进制数位。

与UCS-2编码完全相同。对应的4字节UCS-4编码后两个字节一致,前两个字节的所有位均为0。

需要注意的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

比如,汉字“严”的Unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。

这里就有两个严重的问题,第一个问题是,如何才能区别Unicode和ASCII?计算机怎么知道三个字节表示一个Unicode中的字符,而不是分别表示三个ASCII的 字符呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。

它们造成的结果是:

  1. 出现了Unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示Unicode
  2. Unicode在很长一段时间内无法推广,直到互联网的出现

互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一种Unicode的实现方式。其他实现方式还包括UTF-16和UTF-32,不过在互联网上基本不用。

重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一。

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8的编码规则很简单,只有二条:

  • 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的Unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的
  • 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的Unicode码

下表总结了编码规则,字母x表示可用编码的位。


下面,还是以汉字“严”为例,演示如何实现UTF-8编码。

已知“严”的Unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此“严”的UTF-8编码需要三个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,“严”的UTF-8编码是“11100100 10111000 10100101”,转换成十六进制就是E4B8A5。

通过上一节的例子,可以看到“严”的Unicode码是4E25,UTF-8编码是E4B8A5,两者是不一样的。它们之间的转换可以通过程序实现。

在Windows平台下,有一个最简单的转化方法,就是使用内置的记事本小程序Notepad.exe。打开文件后,点击"文件"→"另存为"会跳出一个对话框,在最底部有一个"编码"的下拉条:


里面有四个选项:ANSI,Unicode,Unicode big Endian 和 UTF-8:

选择完”编码方式“后,点击”保存“按钮,文件的编码方式就立刻转换好了。

下面,举一个实例:

打开”记事本“程序Notepad.exe,新建一个文本文件,内容就是一个”严“字,依次采用ANSI,Unicode,Unicode big Endian 和 UTF-8编码方式保存。

然后,用文本编辑软件UltraEdit的”十六进制功能“,观察该文件的内部编码方式。

  • ANSI

    文件的编码就是两个字节“D1 CF”,这正是“严”的GB2312编码,这也暗示GB2312是采用大头方式存储的

  • Unicode

    编码是四个字节“FF FE 25 4E”,其中“FF FE”表明是小头方式存储,真正的编码是4E25。

  • Unicode big Endian

    编码是四个字节“FE FF 4E 25”,其中“FE FF”表明是大头方式存储。

  • UTF-8

    编码是六个字节“EF BB BF E4 B8 A5”,前三个字节“EF BB BF”表示这是UTF-8编码,后三个“E4B8A5”就是“严”的具体编码,它的存储顺序与编码顺序是一致的

如前所述,Windows中也有自己的一套Code Page的定义。

用对应的某个数字,Code Page Number,即Code Page中的标识符(Identifier),表示相应的字符编码。

而一般Code Page也常缩写为CP

比如,CP936表示GBK中文编码,CP65001表示UTF-8编码,CP54936表示GB18030编码,CP950表示BIG5繁体中文等等。

[提示] C#中使用当前系统默认编码处理字符

对于C#来说,处理字符时涉及可能在不同环境中使用的话,那么最好用系统默认编码:

StreamReader reader = new StreamReader(path, System.Text.Encoding.Default);

Windows中的Code Page,按照引用领域来划分,可以分为两类:ANSI Code Page和 OEM Code Page

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,目前的各种叫法,可以理解为:

ANSI = Windows 1252 = CP 1252 = Windows code page 1252 = Windows Latin-1

先说一下本地编码,所谓本地编码,即当前Windows中的二进制的值,用何种编码去解析,然后显示出对应的该编码中的字符。

即,当然系统使用什么类型的编码。

而ANSI编码,根据前面内容得知,只是一个普通的对应于Windows 1252的一个编码而已。并不是其他某些编码合集的总称。

但是有时候,却又看到有人把ANSI编码解释为“本地编码”,比如[22]

其意思,就是[30]中所说的,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输出函数自动处理,才可以正确显示。

( 中国大陆的标准)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)

表 A.7. 微软的代码页标识符(Code Page Identifiers)

Identifier .NET Name Additional information
037 IBM037 IBM EBCDIC US-Canada
437 IBM437 OEM United States
500 IBM500 IBM EBCDIC International
708 ASMO-708 Arabic (ASMO 708)
709   Arabic (ASMO-449+, BCON V4)
710   Arabic - Transparent Arabic
720 DOS-720 Arabic (Transparent ASMO); Arabic (DOS)
737 ibm737 OEM Greek (formerly 437G); Greek (DOS)
775 ibm775 OEM Baltic; Baltic (DOS)
850 ibm850 OEM Multilingual Latin 1; Western European (DOS)
852 ibm852 OEM Latin 2; Central European (DOS)
855 IBM855 OEM Cyrillic (primarily Russian)
857 ibm857 OEM Turkish; Turkish (DOS)
858 IBM00858 OEM Multilingual Latin 1 + Euro symbol
860 IBM860 OEM Portuguese; Portuguese (DOS)
861 ibm861 OEM Icelandic; Icelandic (DOS)
862 DOS-862 OEM Hebrew; Hebrew (DOS)
863 IBM863 OEM French Canadian; French Canadian (DOS)
864 IBM864 OEM Arabic; Arabic (864)
865 IBM865 OEM Nordic; Nordic (DOS)
866 cp866 OEM Russian; Cyrillic (DOS)
869 ibm869 OEM Modern Greek; Greek, Modern (DOS)
870 IBM870 IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2
874 windows-874 ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows)
875 cp875 IBM EBCDIC Greek Modern
932 shift_jis ANSI/OEM Japanese; Japanese (Shift-JIS)
936 gb2312 ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)
949 ks_c_5601-1987 ANSI/OEM Korean (Unified Hangul Code)
950 big5 ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5)
1026 IBM1026 IBM EBCDIC Turkish (Latin 5)
1047 IBM01047 IBM EBCDIC Latin 1/Open System
1140 IBM01140 IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro)
1141 IBM01141 IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro)
1142 IBM01142 IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro)
1143 IBM01143 IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro)
1144 IBM01144 IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro)
1145 IBM01145 IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro)
1146 IBM01146 IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro)
1147 IBM01147 IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro)
1148 IBM01148 IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro)
1149 IBM01149 IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro)
1200 utf-16 Unicode UTF-16, little endian byte order (BMP of ISO 10646); available only to managed applications
1201 unicodeFFFE Unicode UTF-16, big endian byte order; available only to managed applications
1250 windows-1250 ANSI Central European; Central European (Windows)
1251 windows-1251 ANSI Cyrillic; Cyrillic (Windows)
1252 windows-1252 ANSI Latin 1; Western European (Windows)
1253 windows-1253 ANSI Greek; Greek (Windows)
1254 windows-1254 ANSI Turkish; Turkish (Windows)
1255 windows-1255 ANSI Hebrew; Hebrew (Windows)
1256 windows-1256 ANSI Arabic; Arabic (Windows)
1257 windows-1257 ANSI Baltic; Baltic (Windows)
1258 windows-1258 ANSI/OEM Vietnamese; Vietnamese (Windows)
1361 Johab Korean (Johab)
10000 macintosh MAC Roman; Western European (Mac)
10001 x-mac-japanese Japanese (Mac)
10002 x-mac-chinesetrad MAC Traditional Chinese (Big5); Chinese Traditional (Mac)
10003 x-mac-korean Korean (Mac)
10004 x-mac-arabic Arabic (Mac)
10005 x-mac-hebrew Hebrew (Mac)
10006 x-mac-greek Greek (Mac)
10007 x-mac-cyrillic Cyrillic (Mac)
10008 x-mac-chinesesimp MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac)
10010 x-mac-romanian Romanian (Mac)
10017 x-mac-ukrainian Ukrainian (Mac)
10021 x-mac-thai Thai (Mac)
10029 x-mac-ce MAC Latin 2; Central European (Mac)
10079 x-mac-icelandic Icelandic (Mac)
10081 x-mac-turkish Turkish (Mac)
10082 x-mac-croatian Croatian (Mac)
12000 utf-32 Unicode UTF-32, little endian byte order; available only to managed applications
12001 utf-32BE Unicode UTF-32, big endian byte order; available only to managed applications
20000 x-Chinese_CNS CNS Taiwan; Chinese Traditional (CNS)
20001 x-cp20001 TCA Taiwan
20002 x_Chinese-Eten Eten Taiwan; Chinese Traditional (Eten)
20003 x-cp20003 IBM5550 Taiwan
20004 x-cp20004 TeleText Taiwan
20005 x-cp20005 Wang Taiwan
20105 x-IA5 IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5)
20106 x-IA5-German IA5 German (7-bit)
20107 x-IA5-Swedish IA5 Swedish (7-bit)
20108 x-IA5-Norwegian IA5 Norwegian (7-bit)
20127 us-ascii US-ASCII (7-bit)
20261 x-cp20261 T.61
20269 x-cp20269 ISO 6937 Non-Spacing Accent
20273 IBM273 IBM EBCDIC Germany
20277 IBM277 IBM EBCDIC Denmark-Norway
20278 IBM278 IBM EBCDIC Finland-Sweden
20280 IBM280 IBM EBCDIC Italy
20284 IBM284 IBM EBCDIC Latin America-Spain
20285 IBM285 IBM EBCDIC United Kingdom
20290 IBM290 IBM EBCDIC Japanese Katakana Extended
20297 IBM297 IBM EBCDIC France
20420 IBM420 IBM EBCDIC Arabic
20423 IBM423 IBM EBCDIC Greek
20424 IBM424 IBM EBCDIC Hebrew
20833 x-EBCDIC-KoreanExtended IBM EBCDIC Korean Extended
20838 IBM-Thai IBM EBCDIC Thai
20866 koi8-r Russian (KOI8-R); Cyrillic (KOI8-R)
20871 IBM871 IBM EBCDIC Icelandic
20880 IBM880 IBM EBCDIC Cyrillic Russian
20905 IBM905 IBM EBCDIC Turkish
20924 IBM00924 IBM EBCDIC Latin 1/Open System (1047 + Euro symbol)
20932 EUC-JP Japanese (JIS 0208-1990 and 0121-1990)
20936 x-cp20936 Simplified Chinese (GB2312); Chinese Simplified (GB2312-80)
20949 x-cp20949 Korean Wansung
21025 cp1025 IBM EBCDIC Cyrillic Serbian-Bulgarian
21027   (deprecated)
21866 koi8-u Ukrainian (KOI8-U); Cyrillic (KOI8-U)
28591 iso-8859-1 ISO 8859-1 Latin 1; Western European (ISO)
28592 iso-8859-2 ISO 8859-2 Central European; Central European (ISO)
28593 iso-8859-3 ISO 8859-3 Latin 3
28594 iso-8859-4 ISO 8859-4 Baltic
28595 iso-8859-5 ISO 8859-5 Cyrillic
28596 iso-8859-6 ISO 8859-6 Arabic
28597 iso-8859-7 ISO 8859-7 Greek
28598 iso-8859-8 ISO 8859-8 Hebrew; Hebrew (ISO-Visual)
28599 iso-8859-9 ISO 8859-9 Turkish
28603 iso-8859-13 ISO 8859-13 Estonian
28605 iso-8859-15 ISO 8859-15 Latin 9
29001 x-Europa Europa 3
38598 iso-8859-8-i ISO 8859-8 Hebrew; Hebrew (ISO-Logical)
50220 iso-2022-jp ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS)
50221 csISO2022JP ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana)
50222 iso-2022-jp ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI)
50225 iso-2022-kr ISO 2022 Korean
50227 x-cp50227 ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022)
50229   ISO 2022 Traditional Chinese
50930   EBCDIC Japanese (Katakana) Extended
50931   EBCDIC US-Canada and Japanese
50933   EBCDIC Korean Extended and Korean
50935   EBCDIC Simplified Chinese Extended and Simplified Chinese
50936   EBCDIC Simplified Chinese
50937   EBCDIC US-Canada and Traditional Chinese
50939   EBCDIC Japanese (Latin) Extended and Japanese
51932 euc-jp EUC Japanese
51936 EUC-CN EUC Simplified Chinese; Chinese Simplified (EUC)
51949 euc-kr EUC Korean
51950   EUC Traditional Chinese
52936 hz-gb-2312 HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ)
54936 GB18030 Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030)
57002 x-iscii-de ISCII Devanagari
57003 x-iscii-be ISCII Bengali
57004 x-iscii-ta ISCII Tamil
57005 x-iscii-te ISCII Telugu
57006 x-iscii-as ISCII Assamese
57007 x-iscii-or ISCII Oriya
57008 x-iscii-ka ISCII Kannada
57009 x-iscii-ma ISCII Malayalam
57010 x-iscii-gu ISCII Gujarati
57011 x-iscii-pa ISCII Punjabi
65000 utf-7 Unicode (UTF-7)
65001 utf-8 Unicode (UTF-8)

字符编码详解

标签:des   style   blog   http   color   io   os   使用   ar   

广告服务联系QQ:1134687142 | 网站地图

版权所有: IT货架- 内容来自互联网,仅供用于技术学习,请遵循相关法律法规. 京ICP备11030978号-1