Java direct ByteBuffer-解码字符

Java direct ByteBuffer-解码字符,java,encoding,nio,bytebuffer,direct-buffer,Java,Encoding,Nio,Bytebuffer,Direct Buffer,我希望将字节读入direct ByteBuffer,然后在不将原始缓冲区重新写入byte[]数组的情况下对其进行解码,以最小化内存分配 因此,我希望避免使用StandardCharsets.UTF_8.decode(),因为它在堆上分配新数组 我被困在如何解码字节上。考虑下面的代码,该代码将字符串写入缓冲区,然后再次读取ID。 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(2 << 16); byteBuffer.put("He

我希望将字节读入direct 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());
}

如何解码缓冲区?

您不能指定
字符缓冲区的编码。请看这里:

另外,由于缓冲区是可变的,我不知道如何从中创建一个始终不可变的
字符串,而不进行内存重新分配

我希望将字节读入direct ByteBuffer,然后在不将原始缓冲区重新写入byte[]数组的情况下对其进行解码,以最小化内存分配

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

这个方法的意思是:

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

虽然没有明确说明,但这是一个提示,
CharBuffer
在给定的缓冲区上使用UTF-16字符编码。由于我们无法控制charbuffer使用的编码方式,因此除了在该编码方式中写入字符字节之外,您没有太多选择

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

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

谢谢你,约翰,但我的问题仍然有效。如何在没有额外内存分配的情况下解码direct ByteBuffer中的字符?您的问题是
如何指定direct CharBuffer中的编码?
但是…我想这应该是一个注释,还是一个重复的接近投票,而不是一个anwser。正如我在回答中已经说过的,您不能这样做,因为Java中的
String
是不可变的,因此如果没有副本,您就不可能这样做(否则您可以通过修改缓冲区来修改
String
。)公平地说,它将重新表述。我对读取单个字符比对整个字符串更感兴趣。您需要翻转
字符缓冲区,
而不是
字节缓冲区。
字符缓冲区不继承翻转状态。
䡥汬漠