编码
参考:博客0
ASCII 编码
规定了 128 个字符编码。只占用一个字节的 7 位,最高位统一为 0
非 ASCII 编码
因为 ASCIi 编码不够,所以需要 GB2312 等编码
Unicode
Unicode,如其名字,给所有符号(包括一些 emoji)进行编码。可查询 <unicode.org>
但 Unicode 只规定了符号的二进制代码,没规定二进制代码如何存储。如严字,Unicode 是十六进制数 4E25
,二进制有 15 位,至少两个字节。还可能需要 3 个字节,4 个字节,甚至更多。
这就有问题。怎么知道一个字符有几个字节。如果规定字节,那么浪费太多。所以这样 Unicode 一直没有推广
UTF-8
UTF-8 是一种 Unicode 的实现方式,是一种变长的编码方式,可以用 1~4 个字节表示一个符号。注意 GB2312,GBK 不是 Unicode 的实现方式
编码规则:
对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码
10 开头的好处即 self-synchronizing code,假设一个及其糟糕的场景,文本开头丢失了一个字节,造成了后续所有文本的失效,当然没有 self-syschronizing 特性的编码还有很多其他坏处,参见 为什么 UTF-8 以 10 开头
ANSI 编码,ANSI 不是一种特定的编码,在不同系统中表示不同的编码,具体是以 Windows code pages 区分,如 936 的 GBK,950 的 Big-5
notepad 中 UTF-8 LE UTF-8 BE 分别代表的是小端还是大端。
Byte_order_mark,每个文件最前面分别加入一个表示编码顺序的字符,用 FEFF 表示(在 Unicode 中代表 零宽度非换行空格),正好两个字节,而且 FF 比 FE 大 1,根据这两个字节谁在前谁在后判断是什么顺序。对于 UTF-8 则是添加其对应的
EF BB BF
来判断。注意这是可选的,添加了反而可能会对一些软件造成干扰