参考资料:

ANSI 是什么编码?(CSDN,作者:imxiangzi)
https://blog.csdn.net/imxiangzi/article/details/77370160

CTF-Wiki(Github)
https://ctf-wiki.github.io/ctf-wiki/

阮一峰的网络日志:字符编码笔记
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

Unicode(UTF-8, UTF-16)令人混淆的概念(博客园,作者:Boblim)
https://www.cnblogs.com/fnlingnzb-learner/p/6163205.html

ASCII 编码

百度百科给出的解释如下:

ASCII 是基于拉丁字母的一套电脑编码系统。
主要用于显示现代英语和其他西欧语言。
它是最通用的信息交换标准。

标准的 ASCII 码使用 7 位二进制数,定义了 128 个字符,涵盖了大小写字母、数字、标点符号以及一些特殊的控制字符。

  • 0 ~ 31 及 127 是控制字符或通信专用字符。
  • 32 ~ 126 都是可以显示的字符。
    • 48 ~ 57 是阿拉伯数字 0 ~ 10
    • 65 ~ 90 是 26 个大写英文字母
    • 91 ~ 122 是 26 个小写英文字母
    • 其他的都是一些标点符号,比如 ‘,’ ‘.’ 等等

扩展的 ASCII 码使用 8 位二进制数,在标准 ASCII 码的基础上新定义了 128 个字符,表示一些新的符号。

ANSI 编码

ANSI 编码

请参阅参考资料 “ANSI 是什么编码?”。
一般来说,ANSI 编码都使用 16 位二进制数(即 2 字节)代表一个字符。

简体中文编码:GB2312、GBK 和 GB18030

GB2312 编码于 1980 年由中国国家标准总局发布。
其基本集收入了 6763 个汉字和 682 个字符,但是要注意,一些罕用字没有被收入。
具体编码标准请参阅相关文档。

GBK 编码于 1995 年发布,是 GB2312 编码的扩展,并且与之兼容。
其中收入了 21003 个汉字(包括部首和构件)和 883 个字符。
具体编码标准请参阅相关文档。

GB18030-2005 编码于 2005 年发布,兼容 GB2312 编码和 GBK 编码,并支持 Unicode(GB 13000)的所有码位。
其中收入了 70244 个汉字(包括多种少数民族文字)。

繁体中文编码:Big5

用到了再写,待补充…

Unicode 编码

Unicode 编码,中文名称 “统一码”、“万国码”…
看这高端大气的名字就知道它有多 nb 了吧?
它为每种语言的每个字符都设定了一个唯一且确定的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
(以上抄自百度百科)

然而,Unicode 仅仅规定了每一个符号对应的二进制编码,却没有规定它的存储方式:
· 究竟使用多少个二进制位/字节进行存储?
· 如何文件使用的是 ASCII 编码还是 Unicode 编码?
· 如果一个英文文档使用 Unicode 编码,那么其势必会造成存储空间的极大浪费。(为什么?)

为了解决这些问题,我们需要一种统一的存储方式。

UTF-8

这里主要介绍的是 UTF-8 编码,可以用于表示 Unicode 标准中的任何字符。

UTF-8 编码是一种针对 Unicode 的可变长度字符编码,因其最小单位为 1 个字节而得名。
其得到广泛应用的重要原因之一是,其编码的第一个字节兼容 ASCII 编码。

其编码规则如下:
· 对于只有 1 个字节的字符,直接按照其 Unicode 编码存储。
· 对于具有 n 个字节的字符,第一个字节的前 n 位设为 1,第 n + 1 位设为 0,后面字节的前两位设为 10,剩下的空从低位到高位填上其 Unicode 码。

UTF-16

除了 UTF-8 之外,还有一种编码方式得到了广泛的使用(比如固件),这就是 UTF-16。

在 Unicode 的第一个版本中,UTF-16 的编码长度是固定的 2 字节,也就是说,只能表示 65536 个字符,这显然是不够用的。
于是在 Unicode 的第二个版本中,UTF-16 也成为了可变长度字符编码,最小单位是一致的。

请注意,UTF-16 编码不兼容 ASCII!!!!!!!!!!!!

编码对应的开头标志

这个东西貌似不太常用,但是姑且先放在这里:
EF BB BF UTF-8
FE FF UTF-16/UCS-2, big endian.
FF FE UTF-16/UCS-2, little endian
FF FE 00 00 UTF-32/UCS-4, little endian.
00 00 FE FF UTF-32/UCS-4, big-endian.

UTF-8 or UTF-16?

请查阅参考资料 “Unicode(UTF-8, UTF-16)令人混淆的概念”。

示例

示例 1:

源文本 1:Miracle
ASCII(16 进制):4D 69 72 61 63 6C 65

示例 2:

源文本 2:我是忧郁沙茶
GBK(16 进制):CED2 CAC7 D3C7 D3F4 C9B3 B2E8
GBK(2 进制):
1100111011010010 1100101011000111
1101001111000111 1101001111110100
1100100110110011 1011001011101000

Unicode(16 进制):6211 662F 5FE7 90C1 6C99 8336
Unicode(2 进制):
0110001000010001 0110011000101111
0101111111100111 1001000011000001
0110110010011001 1000001100110110

UTF-8(16 进制):E68891 E698AF E5BFA7 E98381 E6B299 E88CB6
UTF-8(2 进制):
111001101000100010010001 111001101001100010101111
111001011011111110100111 111010011000001110000001
111001101011001010011001 111010001000110010110110

大端法与小端法

关于编码错误…

锟斤拷烫烫烫

参照一位知乎匿名用户的解释:

GBK 编码传过去,UTF-8 的服务器不认得,给你返回了容错字符,又被 GBK 翻译回了汉字。。

非常常见的编码问题——ANSI 与 UTF-8 的不兼容

先说背景吧。我使用的操作系统是 Windows 10,代码编辑器为 VS Code,采用的默认编码是 UTF-8。

某一天我心血来潮,写了个自动进行 USTC 健康打卡的 Python 脚本,并写了个批处理程序用来每天运行它。
然而,值得注意的是,脚本中的一些提示信息是用中文输出的。
众所周知,Windows 命令行的默认字符编码是 ANSI,在中文系统下就是 GBK。(大概?)
然而,我刚开始写的时候并没有考虑到这个问题……
于是,在我第一次使用批处理程序运行脚本时,它成功输出了一堆乱码……

刚开始,秉持着绝不向 ANSI 低头的决心,我将命令行的编码永久设置为了 UTF-8。
然而设置完成之后我却发现,中文路径的显示出现了问题。

想了想,秉持着绝不向 ANSI 低头的决心,我在批处理文件的开头加了一行:

1
chcp 65001

这就能使得打开的命令行窗口的字符编码更改为 UTF-8,并且不影响其他的命令行程序。