这个问题是关于如何正确解码GB18030中的字节.
我想解码一个用 GBK 编码的字节数组,但发现 Python 和 Java 有时表现不同。
ch = b'\xA6\xDA'
print(ch.decode('gbk'))
引发错误:
UnicodeDecodeError: 'gbk' 编解码器无法解码位置 0 中的字节 0xa6:非法多字节序列
Java 能够解码它。
byte[] data = {(byte) 0xA6, (byte) 0xDA};
String s = new String(data, Charset.forName("GBK"));
System.out.println(s);
看来Python和Java对
GBK
采用了不同的实现方式,对吧?
看来Python和Java对GBK采用了不同的实现方式吧?
是的。 GBK在某种程度上是一种模糊编码,因此不同的平台可能采用不同的实现方式。
对于Python(这里是CPython),GBK到Unicode的映射定义在mappings_cn.h中,它是CP936的strict实现,其中一些非中文字符(如
0xA6DA
)区域未定义。
相比之下,Java中的GBK(这里是OpenJDK 17),其实是一个extended CP936,其中一些额外的非汉字被包含以遵循GB18030/MS936。例如,
0xA6DA
被映射到 Unicode U+E78E
(尽管它是一个私有用户区域)。