0%

字符编码综述

概述

对字符编码情况进行梳理。

二进制

二进制:由 0 或 1 的比特位组成的编码。

bit:比特位,由电平高低衍生的计算机的 0 与 1。

  • 计算机中,所有数据,不论文字、图片、视频、音频,本质上都是二进制 0101 存储的。

ASCII 编码

ASCII(American standard code for information interchange):美国信息交换标准代码,以 8 位 bit 表示不同的字符,最左边为校验位,所以为 $2^7 =128$ 个不同的字符,表大小英文字母、数字、符号、及各种控制字符。

  • 美国人用 8 个可以开合的晶体管(0 或 1)来组成不同的状态,为一个字节(Byte),即 8 个比特位构成一个字节,有 $2^8$ 即 256 种不同的状态,如 A--->00010001 占一个字节, 一个字节的最大整数是二进制 11111111=十进制 255。这些字节组合起来的东西,能实现一些功能,就叫它“计算机”。
  • 当时只有 127 个字符,包括大小写英文字母、数字和一些符号,这个编码表即 ASCII 编码,比如大写字母 A 的编码是 00010001 ,即 65。
    • 前 32 位为非打印控制字符,如 00x10, 终端换行,0x07, 终端嘟嘟叫;
    • 后面的为打印字符:如空格、标点符号、数字、大小写字母分别用连续的字节状态表示,
    • 传到别的国家,127 个字符不够,就添加到 255 位,第 128-255 位称为“扩展字符集”。
  • ANSI 是 ASCII 的扩展,除英文外还可以表示拉丁文。

GB2312 编码

GB2312:ASCII 编码 + 中文,小于 127 的字符与 ASCII 的意义相同,将两个大于 127 的字符连在一起,表示一个汉字,前面的一个字节(他称之为高字节)从 0xA1 用到 0xF7,后面一个字节(低字节)从 0xA1 到 0xFE,这样我们就可以组合出大约 7000 多个简体汉字了;这种汉字方案叫做 “GB2312”。

  • 半角字符:原先在 127 号 ASCII 中的一个字节长的字符。
  • 全角字符:新来的包括对原来的 127 号字符重新编码的两个字节长的称为“全角”字符。

GBK 和 GB18030 编码

GBK:汉字太多,GB2312 不够用,于是规定:只要第一个字节是大于 127 就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为 GBK 标准,GBK 包括了 GB2312 的所有内容,同时又增加了近 20000 个新的汉字(包括繁体字)和符号。
GB18030:少数民族觉得 GBK 也不够用,再扩展,增加了几千个新的少数民族的字,成为了 GB18030。
DBCS:Double Byte Charecter Set: 双字节字符集:中国的程序员通称这些两个字节表示一个字符的标准为 DBCS 系列标准。其最大特点是两字节长的汉字字符与一字节长的英文字符在同一套编码方案里。字串中每个字节的值,若大于 127,则为双字节字符集中的字符。即“一个汉字长等于两个英文字符长”。

万国码 -Unicode

各个国家都要用计算机了,日文编码:Shif_JIS,韩文编码:Euc-kr…现有的编码不够用了,为解决各国的自编码的信息交互问题,ISO(国际标准化组织)废了所有的地区性编码方案,重新搞一个包括了地球上所有文字、字母和符号的编码,即 “Universal Multiple-Octet Coded Character Set”,简称 UCS, 俗称 “UNICODE”。

Unicode:万国码,用两个字节,即 16 位来表示一个字符,有 65535 种不同的字符,足以覆盖世界上所有符号(包括甲骨文)

  • 构造:
    • 对 ASCII 的半角字符,UNICODE 保持其原编码不变,只是将长度由原来的 8 位变为 16 位;
    • 对于 ascii 里的那些“半角”字符,UNICODE 包持其原编码不变,只是将其长度由原来的 8 位扩展为 16 位,而其他文化和语言的字符则全部重新统一编码。
    • 由于 “ 半角 “ 英文符号只需要用到低 8 位,所以其高 8 位永远是 0,因此这种大气的方案在保存英文文本时会多浪费一倍的空间。
  • 评价:
    • UNICODE 没有考虑与任何一种现有编码方案兼容(除了 ASCII),即如 GBK 与 UNICODE 在汉字上的编排完全不一样,只能通过一一对应的速查表才能进行转换。
    • 如前所述,UNICODE 是用两个字节来表示为一个字符,他总共可以组合出 65535 不同的字符,这大概已经可以覆盖世界上所有文化的符号。如果还不够也没有关系,ISO 已经准备了 UCS-4 方案,说简单了就是四个字节来表示一个字符,这样我们就可以组合出 21 亿个不同的字符出来(最高位有其他用途),这大概可以用到银河联邦成立那一天吧!
  • 在数据库中,有 n 前缀的字串类型就是 UNICODE 类型,此时,用两个字节表示一个字符,无论它是汉字还是英文字母,还是其他什么。即 “abc Shawn “,在无 n 前缀的数据类型中,为 5 个字符长度,有 n 前缀的数据类型中,为 4 个字符长度。

UTF-8

UTF-8:8-bit Unicode Transfer Format:可变长编码。面向传输,UTF-8,一次 8 个位传输数据,UTF-16 每次 16 个位

Unicode 编码时代,乱码没有了,但如果都是英文,用 Unicode 比 ASCII 多一倍的空间,如 A 从 ASCII 的 00010001 变成了 Unicode 的 00000000 00010001,这太浪费了。所以出现了 UTF 编码。
unicode 分占 4 个字节的 utf-32,2 个字节的 utf-16,1-4 个字节的 utf-8,其中 utf-16 是现在最常用的 unicode 版本, 不过在文件里存的还是 utf-8,因为 utf8 省空间。
根据不同的符号变化字节长度,当字符在 ASCII 码的范围内时,使用一个字节表示,所以它是兼容 ASCII 编码的。
UTF-8 编码把一个 Unicode 字符根据不同的数字大小编码成 1-6 个字节,常用的英文字母被编码成 1 个字节,汉字通常是 3 个字节,只有很生僻的字符才会被编码成 4-6 个字节。如果你要传输的文本包含大量英文字符,用 UTF-8 编码就能节省空间:

字符ASCIIUnicodeUTF-8
A100000100000000 010000011000001
x01001110 0010110111100100 10111000 10101101
  • Unicode 是规范,是内存编码表示方案
  • UTF:是实现,是保存和传输 Unicode 的方案,
    用记事本编辑的时候,从文件读取的 UTF-8 字符被转换为 Unicode 字符到内存里,编辑完成后,保存的时候再把 Unicode 转换为 UTF-8 保存到文件:
    unicode 是离用户更近的数据,bytes 是离计算机更近的数据。
    ASCII 编码和 Unicode 编码的区别:ASCII 编码是 1 个字节,而 Unicode 编码通常是 2 个字节。

乱码/问号/方块

BOM

BOM:Byte-Order Mark:字节序标记,是 Unicode 码点 U+FEFF。它被定义来放在一个 UTF-16 文件的开头,如果字节序列是 FEFF 那么这个文件就是大端序,如果字节序列是 FFFE 那么这个文件就是小端序。

锟斤拷

在将一些国家语言编码体系,比如 GB、BIG-5、EUC-JP 等,转换为 Unicode 的过程中,多少有一些字符是不在 Unicode 中的(比如一些偏旁部首在 Unicode 里是后来才收录的),甚至它本身在原来的编码体系里面就是非法字符的情况。
Unicode 规定了 U+FFFD 当作一个占位符用来表示这些字符,用 UTF-8 编码它就是 EF BF BD,连续多个这样的字节序列出现就成了 EF BF BD EF BF BD。如果是一个 UTF-8 的解析程序还好,而如果用一个 GB 的解析程序去打开,一个汉字 2 字节,就成了“锟斤拷”。

烫烫烫、屯屯屯

  • VC 在 Debug 模式下,会将未初始化的栈内存全部填写成 0xCC,未初始化的堆内存填成 0xCD,这样便能让开发者一眼看出开了内存没初始化。而在 GBK 编码下,CC CC 就是“”,CD CD 就是“”。

附 1 ASCII 编码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
Bin Dec Hex 缩写/字符 解释
00000000 0 0 NUL(null) 空字符
00000001 1 1 SOH(start of headline) 标题开始
00000010 2 2 STX (start of text) 正文开始
00000011 3 3 ETX (end of text) 正文结束
00000100 4 4 EOT (end of transmission) 传输结束
00000101 5 5 ENQ (enquiry) 请求
00000110 6 6 ACK (acknowledge) 收到通知
00000111 7 7 BEL (bell) 响铃,产生嘟声
00001000 8 8 BS (backspace) 退格
00001001 9 9 HT (horizontal tab) 水平制表符
00001010 10 0A LF (NL line feed, new line) 换行键
00001011 11 0B VT (vertical tab) 垂直制表符
00001100 12 0C FF (NP form feed, new page) 换页键
00001101 13 0D CR (carriage return) 回车键
00001110 14 0E SO (shift out) 不用切换
00001111 15 0F SI (shift in) 启用切换
00010000 16 10 DLE (data link escape) 数据链路转义
00010001 17 11 DC1 (device control 1) 设备控制1
00010010 18 12 DC2 (device control 2) 设备控制2
00010011 19 13 DC3 (device control 3) 设备控制3
00010100 20 14 DC4 (device control 4) 设备控制4
00010101 21 15 NAK (negative acknowledge) 拒绝接收
00010110 22 16 SYN (synchronous idle) 同步空闲
00010111 23 17 ETB (end of trans. block) 传输块结束
00011000 24 18 CAN (cancel) 取消
00011001 25 19 EM (end of medium) 介质中断
00011010 26 1A SUB (substitute) 替补
00011011 27 1B ESC (escape) 换码(溢出)
00011100 28 1C FS (file separator) 文件分割符
00011101 29 1D GS (group separator) 分组符
00011110 30 1E RS (record separator) 记录分离符
00011111 31 1F US (unit separator) 单元分隔符
00100000 32 20 (space) 空格
00100001 33 21 !
00100010 34 22 " 双引号(double quote)
00100011 35 23 #
00100100 36 24 $
00100101 37 25 %
00100110 38 26 &
00100111 39 27 ' 单引号(single quote)
00101000 40 28 (
00101001 41 29 )
00101010 42 2A *
00101011 43 2B +
00101100 44 2C ,
00101101 45 2D -
00101110 46 2E .
101111 47 2F /
110000 48 30 0
110001 49 31 1
110010 50 32 2
110011 51 33 3
110100 52 34 4
110101 53 35 5
110110 54 36 6
110111 55 37 7
111000 56 38 8
111001 57 39 9
111010 58 3A :
111011 59 3B ;
111100 60 3C <
111101 61 3D =
111110 62 3E >
111111 63 3F ?
1000000 64 40 @
1000001 65 41 A
1000010 66 42 B
1000011 67 43 C
1000100 68 44 D
1000101 69 45 E
1000110 70 46 F
1000111 71 47 G
1001000 72 48 H
1001001 73 49 I
1001010 74 4A J
1001011 75 4B K
1001100 76 4C L
1001101 77 4D M
1001110 78 4E N
1001111 79 4F O
1010000 80 50 P
1010001 81 51 Q
1010010 82 52 R
1010011 83 53 S
1010100 84 54 T
1010101 85 55 U
1010110 86 56 V
1010111 87 57 W
1011000 88 58 X
1011001 89 59 Y
1011010 90 5A Z
1011011 91 5B [
1011100 92 5C \ 反斜杠(back slash)
1011101 93 5D ]
1011110 94 5E ^
1011111 95 5F _
1100000 96 60 `
1100001 97 61 a
1100010 98 62 b
1100011 99 63 c
1100100 100 64 d
1100101 101 65 e
1100110 102 66 f
1100111 103 67 g
1101000 104 68 h
1101001 105 69 i
1101010 106 6A j
1101011 107 6B k
1101100 108 6C l
1101101 109 6D m
1101110 110 6E n
1101111 111 6F o
1110000 112 70 p
1110001 113 71 q
1110010 114 72 r
1110011 115 73 s
1110100 116 74 t
1110101 117 75 u
1110110 118 76 v
1110111 119 77 w
1111000 120 78 x
1111001 121 79 y
1111010 122 7A z
1111011 123 7B {
1111100 124 7C |
1111101 125 7D }
1111110 126 7E ~
1111111 127 7F DEL (delete) 删除
给博主来一杯卡布奇诺