OC网络学习26:字符编码ASCII、Unicode、UTF-8探索
编码历史
最早只有 128
个字符被编码到计算机里,也就是 大小写英文字母、数字和一些符号
,这个编码表被称为 ASCII
编码。例如:大写字母A的编码是65,小写字母z的编码是122。
但是要处理中文显然1个字节是不够的,至少需要2个字节,而且还不能和ASCII编码冲突,所以,中国制定了 GB2312
编码,用来把 中文
编进去,随着发展,又发现了一些局限,所以就有了 GBK
,再继续往后增加了一些字符(如少数名族字体),GBK扩成了 GB18030
。。你可以想得到的是,全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。
因此,Unicode
应运而生。Unicode
把所有语言都统一到 一套编码
里,这样就不会再有乱码问题了。
Unicode标准也在不断发展,但最常用的是用2个字节表示1个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。
新的问题又出现了:如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就得不偿失。
所以,本着节约的精神,又出现了把Unicode编码转化为 可变长度编码的UTF-8编码
。UTF-8编码 把一个Unicode字符根据不同的数字大小编码成1-6个字节
,常用的 英文字母
被编码成 1个字节
,汉字
通常是 3个字节
,只有 很生僻的字符才会被编码成4-6个字节
。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。
UTF-8编码
有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分。所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。
Charset
Charset(Character set)字符集:是对字符抽象表示的集合。包括世界上各种文字、符号和字符
字符集
只是一个规则集合的名字,对应到真实生活中,字符集就是对某种语言的称呼。例如:汉语、英语、日语
等
字符编码
对于一个字符集来说,要正确编码一个字符需要三个元素:
- 字库表(character repertoire)
字库表:是一个相当于所有可读或者可显示字符的数据库。字库表决定了整个字符集能展现表示的所有字符范文
- 编码字符集(coded character set)
编码字符集:即用一个编码值code point来表示一个字符在字库中的位置
- 字符编码(character encoing)
字符编码:将编码字符集和实际存储数值之间的转换关系
ASCII
ASCII:American Standard Code for Information Interchange,美国信息互换标准代码。
1 | 英文:1个英文字母(不分大小写)占1个字节空间 |
ASCII
只有 128
个字符,表示英文字母的大小写、数字和一些符号
,但由于其他语言用 ASCII
编码表示字节不够。例如:常用中文需要 2
个字节,且不能和ASCII冲突,中国制定了 GB2312
编码格式,相同的,其他国家的语言也有属于自己的编码格式。
Unicode
Unicode
:统一码
,它将世界各种语言里的每一个字符都定义了一个 唯一的编码
。这意味着世界上所有的语言都可以使用它,而不会出现冲突。
1 | 英文:1个英文字母占2个字节空间 |
- 虽然Unicode编码了所有字符,但是在很多情况却不能直接使用它,为什么?
因为在Unicode中有些字符占一个字节,如:英文字符,有些字符则占两个字节,如:常用汉字。但是当我解码一串中英字符混合的Unicode编码时,我是一次解码一个字节呢还是两个字节呢?UTF-8,UTF-16,UTF-32解决了这个问题。
- 转义字符,反斜杠 \
\U
后跟8位16进制数
\u
后跟4位16进制数
UTF
- UTF-8
UTF-8:(8-bit Unicode Transformation Format,Unicode转换格式),它是一种Unicode编码的实现,即 可变长度字符编码
。
1 | 英文:1个英文字母占1个字节空间 |
为了解决上述问题,又出现了 把Unicode编码转化为可变长度编码UTF-8编码
,UTF-8编码将Unicode字符按数字大小编码为1-6个字节,英文字母被编码成1个字节,常用汉字被编码成3个字节
,如果你编译的文本是纯英文的,那么用UTF-8就会非常节省空间,并且ASCII码也是UTF-8的一部分。
- 进一步理解
UTF-8编码
为 变长编码
。最小编码单位(code unit)为一个字节。一个字节的前1-3个bit为描述性部分,后面为实际序号部分。
0xxxxxxx
:如果是这样的格式,表示在UTF-8
中这个字符
用这一个字节
即可表示,读取这一个字节即可解码成一个字符。因为第一位已经规定为0
,所以只有7
位能用来放置Unicode编码。110xxxxx 10xxxxxx
:如果是这样的格式,则表示在UTF-8
种这个字符
用两个字节
可以表示,读取两个字节可以解码成一个字符。110
表示此字节为开头字节,10
表示此字节不是开头字节。因为第有5位已经固定,所以仅有11位可以用于存放Unicode编码。1110xxxx 10xxxxxx 10xxxxxx
:如果一个字节以1110
开头,那么代表当前字符
为三字节字符
,占用3个字节的空间。110
之后的所有部分(5个bit)加上后两个字节的除10
外的部分(12个bit)代表在Unicode中的序号。且第二、第三个字节以10开头。
来看一个UTF-8的例子:
发现其中规律:
1个字节的UTF-8十六进制编码是以比8小的数字开头的
2个字节的UTF-8十六进制编码是以C或D开头的
3个字节的UTF-8十六进制编码是以E开头的
UTF-8、UTF-16和UTF-32区别
utf-32
是采用每个字符 使用4个字节
进行存储。utf-16
是采用每个字符 使用2或4个字节
进行存储。U+0000 ~ U+FFFF:使用两个字节表示。
U+10000 ~ U+10FFFF:使用四个字节表示
utf-8 比较特殊,它是
变化的
,根据字符的长度来动态变化,来表示实现编码。- utf-8 遇到纯英文,就用1个字节,8bit位变化来实现,
- utf-8 遇到中文,用2个字节,16bit位变化来实现。
- utf-8 遇到韩文,用3个字节,24bit位变化来实现。
Unicode 和 UTF-8
Unicode
就是上文中提到的 编码字符集
,而 UTF-8就是字符编码
,即Unicode规则字库的一种实现形式。
三种编码之间的联系
在计算机系统通用的字符编码工作方式:
- 在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换成UTF-8编码
- 用记事本编辑的时候,从文件读取的UTF-8字符被转换成Unicode字符到内存中,编辑完成后,保存的时候把Unicode转换为UTF-8保存到文件,如下图:
- Post title:OC网络学习26:字符编码ASCII、Unicode、UTF-8探索
- Post author:张建
- Create time:2023-08-09 08:39:53
- Post link:https://redefine.ohevan.com/2023/08/09/OC网络/OC网络学习26:字符编码ASCII、Unicode、UTF-8探索/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.