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

bop*_*cat 1 java character-encoding

代码段:

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

打印:

[113, 119, 101, 114, 116, 121, 117, 105, 111, 112, 0]
Run Code Online (Sandbox Code Playgroud)

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

我想知道这是否记录在任何地方?

这一页:

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

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

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

s.getBytes(StandardCharsets.UTF_8)
Run Code Online (Sandbox Code Playgroud)

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

那么,java.nio.charset.Charset的编码(String s)应该用于什么?

ken*_*ytm 8

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

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

java.nio.HeapByteBuffer[pos=0 lim=10 cap=11]
Run Code Online (Sandbox Code Playgroud)

ByteBuffer具有限制10(字符串的长度)和容量 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)
Run Code Online (Sandbox Code Playgroud)

当您调用时.array(),它将返回整个后备阵列,因此即使超出限制的内容也将包含在内.

提取Java字节数组的实际方法是通过以下.get()方法:

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

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

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