ASCII、Unicode、UTF-8和UTF-16
# ASCII、Unicode、UTF-8和UTF-16
# 一、ASCII
ASCII 码一共规定了128个字符的编码,比如空格SPACE是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的一位统一规定为0。
码表
十进制 | 对应字符 | 十进制 | 对应字符 | 十进制 | 对应字符 |
---|---|---|---|---|---|
65 | A | 97 | a | 48 | 0 |
66 | B | 98 | b | 49 | 1 |
67 | C | 99 | c | 50 | 2 |
68 | D | 100 | d | 51 | 3 |
69 | E | 101 | e | 52 | 4 |
70 | F | 102 | f | 53 | 5 |
71 | G | 103 | g | 54 | 6 |
72 | H | 104 | h | 55 | 7 |
73 | I | 105 | i | 56 | 8 |
74 | J | 106 | j | 57 | 9 |
75 | K | 107 | k | ||
76 | L | 108 | l | ||
77 | M | 109 | m | ||
78 | N | 110 | n | ||
79 | O | 111 | o | ||
80 | P | 112 | p | ||
81 | Q | 113 | q | ||
82 | R | 114 | r | ||
83 | S | 115 | s | ||
84 | T | 116 | t | ||
85 | U | 117 | u | ||
86 | V | 118 | v | ||
87 | W | 119 | w | ||
88 | X | 120 | x | ||
89 | Y | 121 | y | ||
90 | Z | 122 | z |
或者查看网址
# 二、Unicode
世界上的语言种类很多,依靠ASCII码肯定不能满足所有语言的需求,所以出现了Unicode。
Unicode 是一个很大的集合,现在的规模可以容纳100多万个符号,可以满足所有语言使用。
每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字严。具体的符号对应表,可以查询unicode.org (opens new window),或者专门的汉字对应表 (opens new window)。
需要注意的是,Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
比如,汉字严的 Unicode 是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说,这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
这里就有两个严重的问题
第一个问题是,如何才能区别 Unicode 和 ASCII ? 计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?
第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果 Unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:
1)出现了 Unicode 的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示 Unicode。
2)Unicode 在很长一段时间内无法推广,直到互联网的出现。
# 三、UTF-8和UTF-16
UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式(存储方式),现在绝大部分的网站编码都是采用UTF-8。
浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器:
其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示)不过在互联网上基本不用。
重复一遍,这里的关系是
UTF-8 是 Unicode 的实现方式(存储方式)之一。
UTF-8 最大的一个特点,就是它是一种**变长
的编码方式。它可以使用1~4**个字节表示一个符号
根据不同的符号而变化字节长度。
UTF-8 的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
下表总结了编码规则,字母x
表示可用编码的位。
Unicode符号范围 | UTF-8编码方式 (十六进制) | (二进制) ------------------------------------------------------------------- 0000 0000-0000 007F | 0xxxxxxx 0000 0080-0000 07FF | 110xxxxx 10xxxxxx 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
1
2
3
4
5
6
7
跟据上表,解读 UTF-8 编码非常简单。如果一个字节的第一位是0
,则这个字节单独就是一个字符;如果第一位是1
,则连续有多少个1
,就表示当前字符占用多少个字节。
下面,还是以汉字严
为例,演示如何实现 UTF-8 编码。
严
的 Unicode 是4E25
(100111000100101
)
根据上表,可以发现4E25
处在第三行的范围内(0000 0800 - 0000 FFFF
),因此严
的 UTF-8 编码需要三个字节即格式是1110xxxx 10xxxxxx 10xxxxxx
。
然后,从严
的最后一个二进制位开始,依次从后向前填入格式中的x
,多出的位补0
。
这样就得到了,严
的 UTF-8 编码是11100100 10111000 10100101
,转换成十六进制就是E4B8A5
。
此外,还有UTF-16、UTF-32编码格式
UTF-16采用定长两个字节表示,看起来utf-16更加节省资源,节省空间。
但实际上,当时,互联网上绝大部分存在的资源都是英文的,英文在utf-16中也是2个字节,而在utf-8中则是1个字节。
在当时,显然是utf-8更加节省资源。现在我们在中文世界里来比较他们,则是utf-16更加节省资源。
# 四、总结
ASCII是最早出现的编码格式,8位二进制表示,共128个字符
Unicode的出现是为了解决ASCII表示字符不足
UTF-8 是 Unicode 的实现方式(存储方式)之一,使用范围最广。