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
锟斤拷的成因
有一个文件 A
用 UTF-8 编码读 A,其中不符合 UTF-8 规范的十六进制值被解析为字符
�(Replacement Character)
把 A 保存为 UTF-8 格式的新文件 B,则 � 被记录为 EFBFBD
再用 GBK 编码读文件 B,如果有相邻的两个 �,即 EFBFBDEFBFBD,则读为
EFBF BDEF BFBD
在 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
结果是:锟斤拷锟斤拷一锟轿诧拷锟斤拷锟侥憋拷