Appearance
ASCII码
计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有0
和1
两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。
一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000
到11111111
。
上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码(American Standard Code for Information Interchange,美国信息交换标准代码),一直沿用至今。
ASCII 码一共规定了128个字符的编码,每一个都对应一个7位(bits)的二进制数,最前面的一位统一规定为0
。
包含:控制字符(0-31, 127)
、数字(32-47)
、大写字母(65-90):A-Z
、小写字母(97-122):a-z
、标点符号
非ASCII编码
英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够的。于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é
的编码为130(二进制10000010)。这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号。
不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג)
,在俄语编码中又会代表另一个符号。但是不管怎样,所有这些编码方式中,0-127表示的符号是一样的,不一样的只是128-255的这一段。
至于亚洲国家的文字,使用的符号就更多了,汉字就多达10万左右。一个字节只能表示256种符号,肯定是不够的,就必须使用多个字节表达一个符号。比如:
- GB2312:中国国家标准总局于1980年颁布的一套用于信息交换的汉字编码字符集,适用于汉字处理、汉字通信等系统之间的信息交换。,使用两个字节表示一个汉字,所以理论上最多可以表示 256 x 256 = 65536 个符号。
- GBK:1995年颁布,与GB2312兼容,是GB2312的修订方案,能够表示更多的汉字和其他字符(支持更多的中、日、韩(CJK)汉字)。
- GB18030:使用4字节编码,兼容ASCII、GB2312、GBK。包括2000年编制的GB18030-2000,2005年编制的GB18030-2005。
- Big5:多用于台湾香港等地,主要是收录了繁体字。在包含汉字数量上来说,Big5是GBK的子集,但是二者的编码方式是不同的。
Unicode
世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。
有一种编码,将世界上所有的符号都纳入其中,每一个符号都给予一个独一无二的编码,这就是 Unicode,其规模可以容纳100多万个符号。
- Unicode编码由
16进制数字
表示,前面加上U+
,例如U+0041
表示英语的大写字母A(0041转为10进制为65,与ascii编码中值相同)。 - Unicode字符集被划分为 17 个平面(即,17个区,编号为 0-16 ),每个区有2^16个代码点,因此Unicode字符集共有17 × 65536 = 111 4112 个码点。
- 整个Unicode字符集的码点空间为
U+000000 ~ U+10FFFF
- 具体的符号对应表,可以查询unicode.org,或者专门的汉字对应表。
需要注意的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。 比如,汉字严
的 Unicode 是十六进制数4E25
,转换成二进制数足足有15位(100111000100101
),也就是说,这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
这里就有两个严重的问题,第一个问题是,如何才能区别 Unicode 和 ASCII ?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果 Unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:
1)出现了 Unicode 的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示 Unicode。
2)Unicode 在很长一段时间内无法推广,直到互联网的出现。
UTF-8
互联网的普及,强烈要求出现一种统一的编码方式。UTF-8
就是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16
(字符用两个字节或四个字节表示)和 UTF-32
(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8 是 Unicode 的实现方式之一
。
UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。规则如下:
- 对于
单字节
的符号,字节的第1位
设为0
,后面7位
为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。 - 对于
n字节
的符号(n > 1),第1个
字节的前n位都设为1
,第n+1位设为0
,后面字节的前两位一律设为10
。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
Unicode范围(十六进制) | utf-8编码方式(二进制) | 字节数 |
---|---|---|
0000 0000-0000 007F | 0xxxxxxx | 1 |
0000 0080-0000 07FF | 110xxxxx 10xxxxxx | 2 |
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx | 3 |
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 4 |
即:如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。严
的 Unicode 是4E25(100111000100101
),根据上表,可以发现4E25处在第三行的范围内(0000 0800 - 0000 FFFF),因此严的 UTF-8 编码需要三个字节,即格式是1110xxxx 10xxxxxx 10xxxxxx
。然后,从严的最后一个
二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,严的 UTF-8 编码是11100`100 10`111000 10`100101
,转换成十六进制就是E4B8A5
。
Little endian 和 Big endian
以汉
字严为例,Unicode 码是4E25
,需要用两个字节存储,一个字节是4E
,另一个字节是25
。存储的时候,4E在前,25在后
,这就是 Big endian 方式;25在前,4E在后
,这是 Little endian 方式。
那么很自然的,就会出现一个问题:计算机怎么知道某一个文件到底采用哪一种方式编码?
Unicode 规范定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做零宽度非换行空格
(zero width no-break space),用FEFF
表示。这正好是两个字节,而且FF比FE大1。
- 如果一个文本文件的头两个字节是
FE FF
,就表示该文件采用Big endian; - 如果头两个字节是
FF FE
,就表示该文件采用Little endian。
Unicode编码中表示字节排列顺序的那个文件头,叫做BOM
(byte-order mark),FFFE和FEFF就是不同的BOM。
UTF-8文件的BOM是EF BB BF
,但是UTF-8的字节顺序是不变的,因此这个文件头实际上不起作用。有一些编程语言是ISO-8859-1编码,所以如果用UTF-8针对这些语言编程序,就必须去掉BOM,即保存成“UTF-8—无BOM”的格式才可以,PHP语言就是这样。
ascii编码对照表
十进制 | 二进制 | 字符 | 描述 | 十进制 | 二进制 | 字符 | 描述 | |
---|---|---|---|---|---|---|---|---|
0 | 00000000 | NUL | 空字符 | 65 | 01000001 | A | 大写字母A | |
1 | 00000001 | SOH | 标题开始 | 66 | 01000010 | B | 大写字母B | |
2 | 00000010 | STX | 正文开始 | 67 | 01000011 | C | 大写字母C | |
3 | 00000011 | ETX | 正文结束 | 68 | 01000100 | D | 大写字母D | |
4 | 00000100 | EOT | 传输结束 | 69 | 01000101 | E | 大写字母E | |
5 | 00000101 | ENQ | 请求 | 70 | 01000110 | F | 大写字母F | |
6 | 00000110 | ACK | 确认 | 71 | 01000111 | G | 大写字母G | |
7 | 00000111 | BEL | 响铃 | 72 | 01001000 | H | 大写字母H | |
8 | 00001000 | BS | 退格 | 73 | 01001001 | I | 大写字母I | |
9 | 00001001 | TAB | 水平制表 | 74 | 01001010 | J | 大写字母J | |
10 | 00001010 | LF | 换行 | 75 | 01001011 | K | 大写字母K | |
11 | 00001011 | VT | 垂直制表 | 76 | 01001100 | L | 大写字母L | |
12 | 00001100 | FF | 换页 | 77 | 01001101 | M | 大写字母M | |
13 | 00001101 | CR | 回车 | 78 | 01001110 | N | 大写字母N | |
14 | 00001110 | SO | 移出 | 79 | 01001111 | O | 大写字母O | |
15 | 00001111 | SI | 移入 | 80 | 01010000 | P | 大写字母P | |
16 | 00010000 | DLE | 数据链路转义 | 81 | 01010001 | Q | 大写字母Q | |
17 | 00010001 | DC1 | 设备控制1 | 82 | 01010010 | R | 大写字母R | |
18 | 00010010 | DC2 | 设备控制2 | 83 | 01010011 | S | 大写字母S | |
19 | 00010011 | DC3 | 设备控制3 | 84 | 01010100 | T | 大写字母T | |
20 | 00010100 | DC4 | 设备控制4 | 85 | 01010101 | U | 大写字母U | |
21 | 00010101 | NAK | 否定确认 | 86 | 01010110 | V | 大写字母V | |
22 | 00010110 | SYN | 同步空闲 | 87 | 01010111 | W | 大写字母W | |
23 | 00010111 | ETB | 传输块结束 | 88 | 01011000 | X | 大写字母X | |
24 | 00011000 | CAN | 取消 | 89 | 01011001 | Y | 大写字母Y | |
25 | 00011001 | EM | 媒介结束 | 90 | 01011010 | Z | 大写字母Z | |
26 | 00011010 | SUB | 替补 | 91 | 01011011 | [ | 左方括号 | |
27 | 00011011 | ESC | 转义 | 92 | 01011100 | \ | 反斜杠 | |
28 | 00011100 | FS | 文件分隔符 | 93 | 01011101 | ] | 右方括号 | |
29 | 00011101 | GS | 组分隔符 | 94 | 01011110 | ^ | 插入符号 | |
30 | 00011110 | RS | 记录分隔符 | 95 | 01011111 | _ | 下划线 | |
31 | 00011111 | US | 单元分隔符 | 96 | 01100000 | ` | 反引号 | |
32 | 00100000 | SPACE | 空格 | 97 | 01100001 | a | 小写字母a | |
33 | 00100001 | ! | 感叹号 | 98 | 01100010 | b | 小写字母b | |
34 | 00100010 | " | 引号 | 99 | 01100011 | c | 小写字母c | |
35 | 00100011 | # | 井号 | 100 | 01100100 | d | 小写字母d | |
36 | 00100100 | $ | 美元符 | 101 | 01100101 | e | 小写字母e | |
37 | 00100101 | % | 百分号 | 102 | 01100110 | f | 小写字母f | |
38 | 00100110 | & | 和符 | 103 | 01100111 | g | 小写字母g | |
39 | 00100111 | ' | 单引号 | 104 | 01101000 | h | 小写字母h | |
40 | 00101000 | ( | 左括号 | 105 | 01101001 | i | 小写字母i | |
41 | 00101001 | ) | 右括号 | 106 | 01101010 | j | 小写字母j | |
42 | 00101010 | * | 星号 | 107 | 01101011 | k | 小写字母k | |
43 | 00101011 | + | 加号 | 108 | 01101100 | l | 小写字母l | |
44 | 00101100 | , | 逗号 | 109 | 01101101 | m | 小写字母m | |
45 | 00101101 | - | 减号 | 110 | 01101110 | n | 小写字母n | |
46 | 00101110 | . | 句号 | 111 | 01101111 | o | 小写字母o | |
47 | 00101111 | / | 斜杠 | 112 | 01110000 | p | 小写字母p | |
48 | 00110000 | 0 | 数字0 | 113 | 01110001 | q | 小写字母q | |
49 | 00110001 | 1 | 数字1 | 114 | 01110010 | r | 小写字母r | |
50 | 00110010 | 2 | 数字2 | 115 | 01110011 | s | 小写字母s | |
51 | 00110011 | 3 | 数字3 | 116 | 01110100 | t | 小写字母t | |
52 | 00110100 | 4 | 数字4 | 117 | 01110101 | u | 小写字母u | |
53 | 00110101 | 5 | 数字5 | 118 | 01110110 | v | 小写字母v | |
54 | 00110110 | 6 | 数字6 | 119 | 01110111 | w | 小写字母w | |
55 | 00110111 | 7 | 数字7 | 120 | 01111000 | x | 小写字母x | |
56 | 00111000 | 8 | 数字8 | 121 | 01111001 | y | 小写字母y | |
57 | 00111001 | 9 | 数字9 | 122 | 01111010 | z | 小写字母z | |
58 | 00111010 | : | 冒号 | 123 | 01111011 | { | 左大括号 | |
59 | 00111011 | ; | 分号 | 124 | 01111100 | | | 竖线 | |
60 | 00111100 | < | 小于号 | 125 | 01111101 | } | 右大括号 | |
61 | 00111101 | = | 等号 | 126 | 01111110 | ~ | 波浪号 | |
62 | 00111110 | > | 大于号 | 127 | 01111111 | DEL | 删除 | |
63 | 00111111 | ? | 问号 | |||||
64 | 01000000 | @ | 电子邮件符号 |