字符串字节编码问题



假设我有以下函数

static void fun(String str) {
System.out.println(String.format("%s | length in String: %d | length in bytes: %d | bytes: %s", str, str.length(), str.getBytes().length, Arrays.toString(str.getBytes())));
}

调用fun("ó");时,其输出为

ó | length in String: 1 | length in bytes: 2 | bytes: [-61, -77]

因此,这意味着characteró需要2个字节来表示,根据character类文档,考虑到当我执行时,java中的默认值是UTF-16

System.out.println(new String("ó".getBytes(), StandardCharsets.UTF_16));// output=쎳
System.out.println(new String("ó".getBytes(), StandardCharsets.ISO_8859_1));// output=ó
System.out.println(new String("ó".getBytes(), StandardCharsets.US_ASCII));// output=��
System.out.println(new String("ó".getBytes(), StandardCharsets.UTF_8));// output=ó
System.out.println(new String("ó".getBytes(), StandardCharsets.UTF_16BE));// output=쎳
System.out.println(new String("ó".getBytes(), StandardCharsets.UTF_16LE));// output=돃

既然字节表示16位长度的字符,为什么UTF_16、UTF_16BE和UTF_16LE字符集中的任何一个都无法正确解码字节?以及UTF-8如何正确解码,因为UTF-8认为每个字符只有8位长,所以它应该像ISO_8859_1一样打印2个字符(每个字节1个字符(。

getBytes总是返回平台默认字符集中编码的字节,对您来说可能是UTF-8。

使用平台的默认字符集将此字符串编码为一个字节序列,并将结果存储到一个新的字节数组中。

因此,您实际上是在尝试用非UTF-8字符集解码一堆UTF-8字节。难怪你没有得到预期的结果。

尽管这有点毫无意义,但您可以通过将所需的字符集传递给getBytes来获得所需的内容,以便对字符串进行正确编码。

System.out.println(new String("ó".getBytes(StandardCharsets.UTF_16), StandardCharsets.UTF_16));
System.out.println(new String("ó".getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.ISO_8859_1));
System.out.println(new String("ó".getBytes(StandardCharsets.US_ASCII), StandardCharsets.US_ASCII));
System.out.println(new String("ó".getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));
System.out.println(new String("ó".getBytes(StandardCharsets.UTF_16BE), StandardCharsets.UTF_16BE));
System.out.println(new String("ó".getBytes(StandardCharsets.UTF_16LE), StandardCharsets.UTF_16LE));

你似乎对编码也有一些误解。这不仅仅是关于字符占用的字节数。两种编码的每个字符的字节数相同并不意味着它们彼此兼容。此外,在UTF-8中,它并不总是每个字符一个字节。UTF-8是一种可变长度编码。

最新更新