这个问题具体问为什么我从这个编码中得到空值,并且不是关于如何将字符串转换为字节数组的一般性问题。
我的实际用例涉及我的输入是一个字符数组,我想将其作为编码字节数组写入磁盘。
为什么当我尝试以这种方式对字符串进行编码时,结果会尾随空值?
String someInput = "///server///server///server///";
char[] chars = someInput.toCharArray();
Charset encoding = StandardCharsets.UTF_8;
CharBuffer buf = CharBuffer.wrap(chars);
for (byte b : encoding.newEncoder().encode(buf).array())
System.out.println("-> " + new Character((char)b));
输出如下。请注意,在结果示例中,我已使用'�'替换了空值。 Unicode字符可提高可见性。
-> /
-> /
-> /
-> s
-> e
-> r
-> v
-> e
-> r
-> /
-> /
-> /
-> s
-> e
-> r
-> v
-> e
-> r
-> /
-> /
-> /
-> s
-> e
-> r
-> v
-> e
-> r
-> /
-> /
-> /
-> �
-> �
-> �
答案 0 :(得分:1)
创建基础数组时,它不知道它应该有多大,并且一次增加多个字节/字符(一次添加一个字节效率非常低)
但是,一旦完成文本的转换,它就不会缩小数组以使其变小(或复制),因为这也会很昂贵。
简而言之,您不能假设底层缓冲区正好是它需要的大小,它可能更大。您应该将position()和limit()视为要使用的字节的边界。
答案 1 :(得分:1)
我同意@Peter的答案,他是对的,我只想添加一个与之相关的查找,我调试这段代码并发现在下面的for循环中: 在电话会议上:
encoding.newEncoder().encode(buf).array()
我调试encode(buf)
方法调用,发现在CharsetEncoder.java
文件中,在encode()方法中,在开始实际编码之前,它计算缓冲区大小以通过下面的行分配编码字节:
int n = (int)(in.remaining() * averageBytesPerChar());
此处 averageBytesPerChar()返回1.1,输入的大小(“ /// server /// server /// server /// ”)是30,这就是为什么总的大小 新分配的缓冲区,即n变为33。
这就是为什么在输出中你会看到3个额外的空格。希望它能帮助你更多地理解。