Java direct ByteBuffer - 解码字符

时间:2017-04-14 09:19:00

标签: java encoding nio bytebuffer direct-buffer

我想将字节读入直接ByteBuffer然后解码它们,而不将原始缓冲区重新包装到byte []数组中以最小化内存分配。

因此我想避免使用StandardCharsets.UTF_8.decode(),因为它在堆上分配新数组。

我坚持如何解码字节。请考虑以下代码,将字符串写入缓冲区,然后再次读取id。

ByteBuffer byteBuffer = ByteBuffer.allocateDirect(2 << 16);

byteBuffer.put("Hello Dávid".getBytes(StandardCharsets.UTF_8));

byteBuffer.flip();

CharBuffer charBuffer = byteBuffer.asCharBuffer();
for (int i = charBuffer.position(); i < charBuffer.length(); i++) {
    System.out.println(charBuffer.get());
}

代码输出:

䡥汬漠

如何解码缓冲区?

2 个答案:

答案 0 :(得分:2)

  

我想将字节读入直接ByteBuffer,然后解码它们,而不将原始缓冲区重新包装到byte []数组中,以最小化内存分配。

实际上,

ByteBuffer.asCharBuffer()符合您的需要,因为两个包装器共享相同的底层缓冲区。

此方法的javadoc说:

  

新缓冲区的位置将为零,其容量和限制将是此缓冲区中剩余的字节数除以2

虽然没有明确说明,但它提示CharBuffer在给定缓冲区上使用UTF-16字符编码。由于我们无法控制charbuffer使用的编码,因此您没有多少选择,但必须在该编码中写入字符字节。

byteBuffer.put("Hello Dávid".getBytes(StandardCharsets.UTF_16));

关于打印for循环的一件事。请注意,CharBuffer.length()实际上是缓冲区位置和限制之间剩余字符数,因此当您调用CharBuffer.get()时它会减少。因此,您应该使用get(int)或将for终止条件更改为limit()

答案 1 :(得分:1)

您无法指定CharBuffer的编码。见这里:What Charset does ByteBuffer.asCharBuffer() use?

此外,由于缓冲区是可变的,我不知道你怎么可能从它创建一个String,它总是不可变的而不进行内存重新分配......