我想将字节读入直接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());
}
代码输出:
䡥汬漠
如何解码缓冲区?
答案 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
,它总是不可变的而不进行内存重新分配......