字符串编码为UTF-8字节时添加空字符?

时间:2017-03-20 20:07:56

标签: java character-encoding

代码段:

public static void main(String[] args) {
    String s = "qwertyuiop";
    System.out.println(Arrays.toString(Charset
       .forName("UTF-8")
       .encode(s)
       .array()));
}

打印:

[113, 119, 101, 114, 116, 121, 117, 105, 111, 112, 0]

这似乎发生了,因为在引擎盖下,对于java.nio.charset.CharsetEncoder类中的UTF-8,averageBytesPerChar变量似乎是1.1。因此它分配11个字节而不是10个字节,如果输入字符串只包含好的旧单字节字符,我最后得到奇数空字符。

我想知道这是否记录在哪里?

此页:

https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html#encode(java.lang.String)

没有提供有关此类行为的线索。

P上。 S.我是否正确无论如何,上述代码段最好由以下代码替换:

s.getBytes(StandardCharsets.UTF_8)

我从其来源看到的还会修剪结果以避免那些空字符?

然后,java.nio.charset.Charset编码(字符串s)应该用于什么?

2 个答案:

答案 0 :(得分:8)

问题不在Charset.encode(),而在于Buffer.array()

如果您打印Charset.forName("UTF-8").encode(s),您会发现输出为

java.nio.HeapByteBuffer[pos=0 lim=10 cap=11]

ByteBuffer的长度限制为10,字符串的长度为 capacity 11,即缓冲区的总分配大小。如果您更改编码,则限制和容量可能会有更大的变化,例如

System.out.println(Charset.forName("UTF-16").encode(s));
// java.nio.HeapByteBuffer[pos=0 lim=22 cap=41]
// (2 extra bytes because of the BOM, not null-termination)

当你call .array()时,它将返回整个后备数组,因此即使包含超出限制的内容也是如此。

提取Java字节数组的实际方法是the .get() method

ByteBuffer buf = Charset.forName("UTF-8").encode(s);
byte[] encoded = new byte[buf.limit()];
buf.get(encoded);
System.out.println(Arrays.toString(encoded));

这看起来像一团糟?因为“nio”表示 N 强烈 I / O 。创建Buffer类型,以便它可以轻松地包装C数组。它使得与本机代码交互(例如读/写文件或发送/接收网络数据)非常有效。这些NIO API通常直接使用Buffer,而不会在其间构建任何byte[]。如果您只使用Buffer,则不需要存在中间的两行:)。

如果整个操作都在Java中,那么只需调用s.getBytes(StandardCharsets.UTF_8)

答案 1 :(得分:0)

如果您只想查看编码为UTF8的String的字节数组,那么只需使用getBytes(Charset charset)方法。它可能看起来像这样:

AddCommentMessage

您将看到每个字符有2个字节。您的输出符合String hello = "qwertyuiop"; byte[] helloBytes_UTF_8 = hello.getBytes(StandardCharsets.UTF_8); 字符集。如果你想用不同的编码玩更多,那么我建议使用一个带有一些工具的小型开源库,其中一个允许你将字符串转换为UNICODE(UTF-8)表示并返回。 Open Source Java library with stack trace filtering, Silent String parsing Unicode converter and Version comparison。本文介绍了库以及如何使用它。您也可以下载源代码和javadoc。特别要查找段落" 字符串Unicode转换器"。使用此类,您将字符串StandardCharsets.ISO_8859_1转换为:"qwertyuiop" \ u符号后面的每四个数字代表十六进制表示的2个字节(一个字符)。