Java 字符串 "hello" 在 getBytes("UTF-16") 时有 12 个字节?
Java string "hello" has 12 bytes when getBytes("UTF-16")?
我预计,当一个 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);
将打印“5 12”
我的问题:
(1) 正如我提到的,我预计第一个 println 应该得到“10”。但为什么是 5?
(2) 对于第二个 println,我试图首先将其作为 "UTF-8" 然后作为 "UTF-16" 获取字节。我想它也应该是10。但实际上是12。
我正在使用 MAC,我所在的地区是香港。你能帮忙解释一下程序中发生了什么,以及“5 12”实际上是如何产生的吗?
非常感谢!
(1) I expected that the first println should get "10" as I mentioned. But why 5?
您采用 5 个字符的字符串,使用 UTF-16 编码将其编码为字节。
然后你通过从 UTF-16 中(正确地)解码字节来创建一个新的字符串,它再次为你提供一个由原来的 5 个字符组成的新字符串。
(2) For the second println, I am trying to getBytes for it first as "UTF-8" then as "UTF-16". I suppose it should also be 10. But actually it's 12.
这部分代码:
new String(h.getBytes("UTF-8"), "UTF-8")
实际上是空操作。这只是复制字符串的一种相当昂贵的方法。您使用 UTF-8 作为编码方案将字符串编码为字节,然后通过解码 UTF-8 编码字节来创建新字符串。
如此有效,您正在这样做:
"hello".getBytes("UTF-16").length
多出2个字节的原因是UTF-16编码将BOM(字节顺序标记)作为第一个(2字节)代码单元。
有关详细信息,请阅读 "UTF-8, UTF-16, UTF-32 & BOM" 上的 Unicode 常见问题解答。
I expected that the first println should get "10" as I mentioned. But why 5?
您在 String
上呼叫 length()
,而不是 byte[]
。因此,这将为您提供 个字符 中的字符串长度(至少只要我们停留在 Unicode 基本多语言平面中——不幸的是,当您有需要可变的字符时,这会崩溃- 即使在 UTF-16 中也是长度编码)。
一旦你有了一个字符串,使用什么编码来创建它就无关紧要了。 length
总是以字符形式给出。
如果您使用 UTF-16 将其转换为 byte[]
,您可能理所当然地期望 10(五个字符乘以每个两个字节)——它实际上最终为 12 是由于包含字节顺序标记。
我预计,当一个 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);
将打印“5 12”
我的问题:
(1) 正如我提到的,我预计第一个 println 应该得到“10”。但为什么是 5?
(2) 对于第二个 println,我试图首先将其作为 "UTF-8" 然后作为 "UTF-16" 获取字节。我想它也应该是10。但实际上是12。
我正在使用 MAC,我所在的地区是香港。你能帮忙解释一下程序中发生了什么,以及“5 12”实际上是如何产生的吗?
非常感谢!
(1) I expected that the first println should get "10" as I mentioned. But why 5?
您采用 5 个字符的字符串,使用 UTF-16 编码将其编码为字节。
然后你通过从 UTF-16 中(正确地)解码字节来创建一个新的字符串,它再次为你提供一个由原来的 5 个字符组成的新字符串。
(2) For the second println, I am trying to getBytes for it first as "UTF-8" then as "UTF-16". I suppose it should also be 10. But actually it's 12.
这部分代码:
new String(h.getBytes("UTF-8"), "UTF-8")
实际上是空操作。这只是复制字符串的一种相当昂贵的方法。您使用 UTF-8 作为编码方案将字符串编码为字节,然后通过解码 UTF-8 编码字节来创建新字符串。
如此有效,您正在这样做:
"hello".getBytes("UTF-16").length
多出2个字节的原因是UTF-16编码将BOM(字节顺序标记)作为第一个(2字节)代码单元。
有关详细信息,请阅读 "UTF-8, UTF-16, UTF-32 & BOM" 上的 Unicode 常见问题解答。
I expected that the first println should get "10" as I mentioned. But why 5?
您在 String
上呼叫 length()
,而不是 byte[]
。因此,这将为您提供 个字符 中的字符串长度(至少只要我们停留在 Unicode 基本多语言平面中——不幸的是,当您有需要可变的字符时,这会崩溃- 即使在 UTF-16 中也是长度编码)。
一旦你有了一个字符串,使用什么编码来创建它就无关紧要了。 length
总是以字符形式给出。
如果您使用 UTF-16 将其转换为 byte[]
,您可能理所当然地期望 10(五个字符乘以每个两个字节)——它实际上最终为 12 是由于包含字节顺序标记。