GBK 与 UTF-8 与锟斤拷的成因

一位十六进制数表示四位二进制数,两位十六进制数表示一个字节。

ASCII 有 128 个符号,使用一个字节表示,范围是 00000000-01111111 即 00-7F

参考:字符编码 / 解码 | SYMBL | HexED.it

GBK

是 GB2312 的超集,有 21886 个符号,使用两个字节表示一个符号。当文本中同时包含 GBK 与 ASCII 字符时,GBK 对 ASCII 字符仍用一个字节表示。

总体编码范围为 8140-FEFE 之间,首字节在 81-FE 之间,避开了 ASCII 的 00-7F,尾字节在 40-FE 之间。

UTF-8

Unicode:为一个符号分配一个码,常用汉字的范围在 U+4E00 到 U+9FFF

UTF-8:使用 1 到 4 个字节表示一个 Unicode 码。其中用 1 个字节表示的与 ASCII 兼容。

用 n 个字节(n>1)表示的,头个字节以 n 个 1 带 1 个 0 开头,后面字节全以 10 开头(在 80-BF 的范围内)。

Unicode UTF-8 第二列各个字节的十六进制范围
0000 0000-0000 007F 0xxxxxxx 00-7F
0000 0080-0000 07FF 110xxxxx 10xxxxxx C0-DF 80-BF
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx E0-EF 80-BF 80-BF
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx F0-F7 80-BF 80-BF 80-BF

如【这】的 Unicode 是 U+8FD9 等于 1000 1111 1101 1001,把它补到空位 x 里:

11101000 10111111 10011001

= E8BF99

锟斤拷的成因

  1. 有一个 GBK 编码的文本文件 A
  2. 用 UTF-8 编码读 A,其中不符合 UTF-8 规范的十六进制值被解析为字符 �(Replacement Character)
  3. 把 A 保存为 UTF-8 格式的新文件 B,则 � 被记录为 EFBFBD
  4. 再用 GBK 编码读文件 B,如果有相邻的两个 �,即 EFBFBDEFBFBD,则读为 EFBF BDEF BFBD
  5. 在 GBK 里,EFBF = 锟,BDEF = 斤,BFBD = 拷
  • 汉字:这是一段测试文本
  • GBK:D5E2 CAC7 D2BB B6CE B2E2 CAD4 CEC4 B1BE
  • 用 UTF-8 编码读它:D5 E2 CA C7 D2BB B6 CEB2 E2 CA D4 CE C4B1 BE
    • D5 表示两字节字符的开始,以 110 开头,但它后面的 E2 并不在 80-BF 的范围之内,于是 D5 被解析为一个 �
    • E2 表示三字节字符的开始,但它后面的 CA 并不在 80-BF 的范围之内,于是 E2 被解析为一个 �
    • ……
    • D2 表示两字节字符的开始,它后面的 BB 在 80-BF 的范围之内
      • 于是:D2 BB = 11010010 10111011
      • 0100 1011 1011 = 4BB
      • U+04BB 为 һ(Cyrillic Small Letter Shha)
    • ……
    • CE 表示两字节字符的开始,它后面的 B2 在 80-BF 的范围之内
      • 于是:CE B2 = 11001110 10110010
      • 0011 1011 0010 = 3B2
      • U+03B2 为 β(Greek Small Letter Beta)
    • ……
    • 读的结果是:����һ�β����ı�
  • 用 UTF-8 的格式保存时
    • � = U+FFFD = U+11111111 11111101
      • 补到 1110xxxx 10xxxxxx 10xxxxxx 里
      • 11101111 10111111 10111101 = EFBFBD
    • 保存的结果是:EFBFBD EFBFBD EFBFBD EFBFBD D2BB EFBFBD CEB2 EFBFBD EFBFBD EFBFBD EFBFBD C4B1 EFBFBD
  • 再用 GBK 编码读
    • EFBF BDEF BFBD EFBF BDEF BFBD D2BB EFBF BDCE B2EF BFBD EFBF BDEF BFBD EFBF BDC4 B1EF BFBD
    • 结果是:锟斤拷锟斤拷一锟轿诧拷锟斤拷锟侥憋拷