将io.netty.buffer.ByteBuf转换为java.nio.ByteBuffer的高效方法

12
我看到了这个查询: Create a ByteBuf in Netty 4.0 ,关于将byte[]转换为ByteBuf和将ByteBuffer转换为ByteBuf。我很好奇如何进行反向转换:
io.netty.buffer.ByteBuf到java.nio.ByteBuffer 并且如何高效地进行操作,最小化/不进行复制? 我进行了一些阅读,并通过一些试验和错误发现了这种低效的转换方式(需要进行两次复制):
// io.netty.handler.codec.http.FullHttpRequest fullHttpRequest;
ByteBuf conByteBuf = fullHttpRequest.content ();                  
int numReadBytes = conByteBuf.readableBytes ();
conBytes = new byte[numReadBytes];
conByteBuf .readBytes (conBytes);                                // First Copy
ByteBuffer conByteBuffer = ByteBuffer.allocate (conBytes.length);
conByteBuffer.put (conByteBuf);                                  // Second Copy

我的问题是,我们能否避免复制操作并使ByteBuffer的内部缓冲区使用ByteBuf的内部缓冲区。

谢谢!

3个回答

13
你应该能够使用ByteBuf.nioBuffers()。这将返回ByteBuf的一个ByteBuffer对象数组视图。
在大多数情况下,这个数组只会有一个元素,但在一些更复杂的ByteBuf实现中,可能存在多个基础ByteBuffer对象,ByteBuf.nioBuffers() 可以原样返回它们,而不是将它们合并成调用ByteBuf.nioBuffer()的结果。
你可以通过使用ByteBuf.nioBufferCount()提前知道数组的长度。

这并不涉及它是否由byte[]支持。 - ruckc
@Dev,当您使用ByteBuf.nioBuffers()ByteBuf.nioBuffer()将ByteBuf作为ByteBuffer对象数组或单个ByteBuffer对象的视图返回时,如果释放了ByteBuf会发生什么?由于ByteBuf和ByteBuffer共享底层数据,因此在此情况下创建的ByteBuffer对象似乎会出现问题。 - mcarlin
1
所以 ByteBuf.nioBuffer() 会自动将它们合并成一个吗?我可以直接调用它而不是在 nioBuffers() 中迭代数组吗? - Dmitry Minkovsky

7
你可以至少使用ByteBuffer.wrap()来避免第二次复制。

我们还能避免第一次复制吗? - Corehacker
2
似乎下面开发者的回复将有助于消除甚至那个问题。 - Kayaman

2

虽然不是特别高效,但已经能够胜任:

public static ByteBuffer toNioBuffer(ByteBuf buffer) {
    if (buffer.isDirect()) {
        return buffer.nioBuffer();
    }
    final byte[] bytes = new byte[buffer.readableBytes()];
    buffer.getBytes(buffer.readerIndex(), bytes);
    return ByteBuffer.wrap(bytes);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接