ascii、unicode和utf-8之前的区别

Eave 2025.08.06

我们经常会听到ascii、unicode、utf-8,对于这些名词概念总是很模糊,似懂非懂,大部分时候不会遇到问题,即使遇到问题百度一下也能解决。其实花几分钟弄清楚这些概念其实很容易,让知识变得具体,下次遇到字符问题,就可以做到心中有数。

什么是ASCII和Unicode

ASCII和Unicode都是字符集,说简单点,就是一个表格,规定97对应英文字母“a”,98对应英文字母“b”,23383对应中文“字”等等,ASCII和Unicode的区别是Unicode这个“表格”更大。

什么是utf-8

utf-8是编码方式的一种,所谓的编码就是一种算法,字符集经过这种算法计算后,变成了另外的数字。比如英文字母a,经过utf-8编码后变成了\u0061,中文“字”经过utf-8编码后变成了\u5b57(十六进制)。

所以,ASCII和Unicode是字符集,而utf-8只是众多编码算法中的一种。接下来我们讨论几个问题,彻底弄明白这些概念。

为什么会有ASCII

ASCII全称是American Standard Code for Information Interchange,美国信息交换标准代码,计算最早是在美国被发明,为了能表示英文字母,就需要有一套处理字符的标准,于是就出现了ASCII。

ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符,用一个字节就可以存储,它等同于国际标准 ISO/IEC 646。

有了ASCII为什么还需要另一种字符集Unicode

ASCII 编码是美国人给自己设计的,英文字母大写加小写总共52个,再算上数字和符号,1字节也足够了(1byte=8bit,最大能表示的数是255)。

于是欧洲那些扩展的拉丁字母,中文、韩语和日语都无法被加入ASCII。

各个国家为了让本国公民也能正常使用计算机,开始效仿 ASCII 开发自己的字符编码,例如 ISO/IEC 8859(欧洲字符集)、shift_Jis(日语字符集)、GBK(中文字符集)等。

这些字符集都有自己的编码,不同语言之间交流因为编码不同而出现乱码,为了解决这个问题就出现了Unicode字符集,Unicode 是国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,字符所在码表的位置叫码点(code point),Unicode字符集的编码范围是 0x0000 - 0x10FFFF(0-1114111),可以容纳一百多万个字符。

为什么需要utf-8

unicode字符集只是规定了字符的二进制代码,却没有规定字符应该如何存储,最简单的方式就是直接存储字符对应的二进制(code point),这种编码方式叫UCS-4,UCS-4使用4个字节来储存1个字符。

但直接存储code point有一个问题:浪费空间,尤其是英文字母1字节就足够了,但用了4倍的空间来存储,造成了严重的空间浪费。

所以才出现了utf-8编码,他是变长编码方式,很好的解决了直接存储code point的问题。

utf-8为什么变成了世界上最流行的编码

先看看utf-8编码算法,他规定一个code point满足:

0 ~ 127 --------> 使用0xxxxxxx 模板存储

128 ~ 2047 -----> 使用110xxxxx 10xxxxxx 模板存储

2048 ~ 65535 ---> 使用1110xxxx 10xxxxxx 10xxxxxx 模板存储

65536 ~ 2097151-> 使用11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 模板存储

例如,汉字“字”utf-8编码过程:

查unicode中的code point是23383

23383在2048 ~ 65535范围内,用1110xxxx 10xxxxxx 10xxxxxx模板。

23383转为二进制是1011_0110_1010_111

这个二进制不足16位,先补足16位:0101_1011_0101_0111

带入模板中:1110_0101_10101101_10010111

转为16进制:\xe5ad97。这就是utf-8编码的“字”

这样设计有就是不同范围的code point使用不同的字节存储,可以节省大量的空间

为什么开头要设计成那样的

这是为了方便解码,从第一个bit开始

如果是0,那后面的1字节(8bit)存储的1个字符

如果非0,就看几个1开头,2个1开头,那后面2个字节(16bit)存储1个字符

3个1开头,后面3个字节(24bit)存储1个字符

4个1开头,后面4个字节(32bit)存储1个字符

为什么从第二个字节开始,都是10开头的

这是为了保证在传输过程中出现中断,也能顺利的找到下一个字符的开头,只需要找到第一个非10开头的字节,就是下一个字符的开头了。

utf-8也能兼容ascii,因为0-127的存储方式0xxxxxxx正好就是ascii的存储方式。

以上这些原因使得utf-8成为了世界上最流行的编码。