略谈计算机编码

最近被问到 Unicode 和 UTF-8 的区别,于是就想起来了,之前也有人问过我这个问题,当时我也是一脸懵逼,于是就去查了一下,然后就忘了,现在又被问到了,于是就想着记录一下。

计算机底层存储都是存储的二进制的编码文件,计算机最初是由美国人发明的,于是他们制定了一组编码规则,其中包含了大小写的英文字母、数字、英文标点符号等,引发了计算机界的编码革命。

ASCII

ASCII(American Standard Code for Information Interchange),美国信息互换标准码。就是美国人最初发明计算机时制定的一组编码,是一种基于拉丁字母的编码,它只有 128 个字符,所以只需要 7 位就可以表示了,所以叫 7 位编码,编码为 0-127。

ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年

ISO-8859-1

由于 ASCII 只占用了 0-127 的范围,后来欧洲开始使用了计算机,于是在 ASCII 的基础上进行了扩展,扩展了 128-255 的范围,这就是 ISO-8859-1,它也是一种 8 位编码,向下兼容 ASCII。Latin1 是 ISO-8859-1 的别名,有些环境下写作 Latin-1,这是 MySQL 的默认编码。

1
2
print(b'\xff'.decode('ISO-8859-1'))
# ÿ

GB2312

后来中国也开始使用计算机,由于汉字的数量很多,ASCII 或 ISO-8859-1 是不够用的,于是就有了 GB2312

GB2312(国标2312) 是一种 16 位编码,也就是 2 个字节,GB2312 标准共收录 6763 个汉字,其中一级汉字 3755 个,二级汉字 3008 个;同时,GB2312 收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的 682 个全角字符。

GB2312 的编码规则是使用两个字节来表示一个汉字,其中两个字节均在 128-255 之间,这样进行编解码时,判断当前字节是否在0~127(ASCII码范围),如果在则表示当前为单字节的英文字母;否则会联合后面的一个字节共同判断当前的汉字表示

GBK

GB2312 并没有收录所有的汉字,而且 GB2312 的编码规则实际上浪费了一部分编码空间,例如当判断了第一个字节范围在 128-255 之间,就可以确定需要联合第二个字节进行解码,于是就有了 GBK

GBK(国标扩) 是 GB2312 的扩展,完全兼容 GB2312 ,共23940个码位,共收录了21003个汉字,

Unicode

由于出现了各种标准的编码,为了统一编码,于是就有了 Unicode

Unicode 是一种字符集,它包含了世界上所有的字符,它的编码范围是 0x0000 到 0x10FFFF,也就是 0 到 1,114,111,所以 Unicode 只是一个字符集,并不是一种在计算机中存储的编码方式

UTF-8

出现了 Unicode 字符集,但例如欧美国家实际上大部分的字符是用不到的,原本一个字节能表示的字符,现在需要用三个字符才能表示,这样就造成了空间的浪费,于是就有了 UTF-8

UTF-8(Unicode Transfer Format 8) 是 Unicode 的一种编码方式,它是一种变长的编码方式,它可以使用 1-4 个字节来表示一个字符,它的编码规则如下

字节 格式 实际编码位 编码范围
1 0xxxxxxx 7 0-127
2 110xxxxx 10xxxxxx 11 128-2047
3 1110xxxx 10xxxxxx 10xxxxxx 16 2048-65535
4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 21 65536-2097151

UTF-16

UTF-16 是 Unicode 的一种编码方式,它是一种变长的编码方式,它可以使用 2-4 个字节来表示一个字符,它的编码规则如下,但是 UTF-16 有一个缺点,就是它不兼容 ASCII,也就是说,如果你的文本中只有英文,那么使用 UTF-16 编码的话,它会占用 2 倍的空间

字节 格式 实际编码位 编码范围 说明
2 xxxxxxxx xxxxxxxx 16 0x000000-0x00ffff 英文 汉字 日文 emoji 等
4 110110yy yyyyyyyy 110111xx xxxxxxxx 20 0x010000-0x10ffff 甲骨文等

UTF-32

UTF-32 是 Unicode 的一种编码方式,它是一种固定长度的编码方式,它使用 4 个字节来表示一个字符

字节 格式 实际编码位 编码范围
4 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 32 0-1114111

ANSI

ANSI 是 American National Standards Institute 的缩写,它是美国国家标准协会的意思,它是一个标准化组织,它制定了一些标准,其中就包括了 ANSI 编码

ANSI 在不同的国家标准不同,

ANSI 编码 国家标准
GBK 中国
BIG5 台湾
EUC-KR 韩国
Shift_JIS 日本
ISO-8859-1 欧洲
ASCII 美国

BOM

BOM 是 Byte Order Mark 的缩写,它的编码是 FEFF ,它是一种标记,用来标记文件的编码格式,它是一个字节序列,它的作用是告诉解码器,当前文件的编码格式是什么,不同编码格式中的 BOM 值如下表

编码格式 BOM 字节序列
UTF-8 EF BB BF
UTF-16BE FE FF
UTF-16LE FF FE
UTF-32BE 00 00 FE FF
UTF-32LE FF FE 00 00