当getBytes("UTF-16")时,Java字符串"hello"有12个字节?

Hin*_*sum 2 java string encode decode

我预计,当一个java字符存储为"UTF-16"时,每个字符使用2个字节,因此"hello"应该消耗10个字节,但是这个代码:

String h = "hello";
System.out.println(new String(h.getBytes("UTF-16"), "UTF-16").length());
System.out.println(new String(h.getBytes("UTF-8"), "UTF-8").getBytes("UTF-16").length);
Run Code Online (Sandbox Code Playgroud)

将打印"5 12"

我的问题:

(1)正如我所提到的,我预计第一个println应该得到"10".但为什么5?

(2)对于第二个println,我试图首先将它作为"UTF-8"然后作为"UTF-16"获取它.我想它也应该是10.但实际上它是12.

我正在使用MAC而我的地区是香港.你能帮忙解释一下程序中发生了什么,以及"5 12"实际上是如何产生的?

非常感谢!

Ste*_*n C 6

(1)正如我所提到的,我预计第一个println应该得到"10".但为什么5?

您使用5个字符的字符串,使用UTF-16编码将其编码为字节.
然后通过从UTF-16解码字节(正确)来创建一个新字符串,它会再次为您提供一个由原始5个字符组成的新字符串.

(2)对于第二个println,我试图首先将它作为"UTF-8"然后作为"UTF-16"获取它.我想它也应该是10.但实际上它是12.

这部分代码:

    new String(h.getBytes("UTF-8"), "UTF-8")
Run Code Online (Sandbox Code Playgroud)

实际上是一个无操作.复制字符串只是一种相当昂贵的方法.使用UTF-8作为编码方案将字符串编码为字节,然后通过解码UTF-8编码的字节来创建新字符串.

如此有效,你这样做:

    "hello".getBytes("UTF-16").length
Run Code Online (Sandbox Code Playgroud)

额外2个字节的原因是UTF-16编码将BOM(字节顺序标记)作为第一个(2字节)代码单元.

有关更多信息,请阅读"UTF-8,UTF-16,UTF-32和BOM"上的Unicode常见问题解答.