繁体   English   中英

字节数组是 Java 中有效的 UTF8 编码字符串,但在 Python 中不是

[英]Byte array is a valid UTF8 encoded String in Java but not in Python

当我在 Python 2.7.6 中运行以下命令时,出现异常:

import base64
some_bytes = b"\x80\x02\x03"
print ("base 64 of the bytes:")
print (base64.b64encode(some_bytes))
try:
    print (some_bytes.decode("utf-8"))
except Exception as e:
    print(e)

输出:

base 64 of the bytes:
gAID
'utf8' codec can't decode byte 0x80 in position 0: invalid start byte

因此,在 Python 2.7.6 中,表示为gAID的字节不是有效的 UTF8。

当我在 Java 8 (HotSpot 1.8.0_74) 中尝试时,使用以下代码:

java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
byte[] bytes = decoder.decode("gAID");
Charset charset = Charset.forName("UTF8");
String s = new String(bytes, charset);

我没有任何例外。

为何如此? 为什么相同的字节数组在 Java 中有效而在 Python 中无效,使用 UTF8 解码?

这是因为 Java 中的 String 构造函数在无效字符的情况下不会抛出异常。 请参阅此处的文档

公共字符串(字节 [] 字节,字符集字符集)

...此方法始终使用此字符集的默认替换字符串替换格式错误的输入和不可映射的字符序列 当需要对解码过程进行更多控制时,应使用 CharsetDecoder 类。

它不是有效的 UTF8。 https://en.wikipedia.org/wiki/UTF-8

0x80 和 0xBF 之间的字节不能是多字节字符的第一个字节。 它们只能是第二个字节或之后的字节。

Java 将无法解码的字节替换为? 而不是抛出异常。

因此,在 Python 2.7.6 中,表示为 gAID 的字节不是有效的 UTF8。

当您尝试解码Base64编码字节时,这是错误的。

import base64
some_bytes = b"\x80\x02\x03"
print ("base 64 of the bytes:")
print (base64.b64encode(some_bytes))
# store the decoded bytes
some_bytes = base64.b64encode(some_bytes)
decoded_bytes = [hex(ord(c)) for c in some_bytes]
print ("decoded bytes: ")
print (decoded_bytes)
try:
    print (some_bytes.decode("utf-8"))
except Exception as e:
    print(e)

输出

gAID
['0x67', '0x41', '0x49', '0x44']
gAID

在 Java 中,您尝试使用 UTF-8 字符集从 Base64 编码的字节创建一个String 在默认替换字符 中的结果(如已回答)。

运行以下代码段

java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
byte[] bytes = decoder.decode("gAID");
System.out.println("base 64 of the bytes:");
for (byte b : bytes) {
    System.out.printf("x%02x ", b);
}
System.out.println();
Charset charset = Charset.forName("UTF8");
String s = new String(bytes, charset);
System.out.println(s);

产生以下输出

base 64 of the bytes:
x80 x02 x03 
?

在那里您可以看到您在 Python 代码段中使用的相同字节。 哪个导致 Python 到'utf8' codec can't decode byte 0x80 in position 0: invalid start byte导致? (它代表非 Unicode 控制台上的默认替换字符)

以下代码段使用来自gAID的字节构造一个带有 UTF-8 字符集的String

byte[] bytes = "gAID".getBytes(StandardCharsets.ISO_8859_1);
for (byte b : bytes) {
    System.out.printf("x%02x ", b);
}
System.out.println();
Charset charset = Charset.forName("UTF8");
String s = new String(bytes, charset);
System.out.println(s);

输出

x67 x41 x49 x44 
gAID

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM