Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient way to convert io.netty.buffer.ByteBuf to java.nio.ByteBuffer

I came across this query: Create a ByteBuf in Netty 4.0 about conversion from byte[] to ByteBuf and ByteBuffer to ByteBuf. I was curious to know about the conversion the other way:

io.netty.buffer.ByteBuf to java.nio.ByteBuffer

and how to do it efficiently, with minimal/no copying? I did some reading and with some trial and error I found this inefficient way of converting it (with two copies):

// 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

My question is, can we avoid one or both the copies and make the internal buffer of ByteBuffer to use the internal buffer of ByteBuf.

Thanks!

like image 277
Corehacker Avatar asked Oct 10 '13 18:10

Corehacker


People also ask

How do I get ByteBuffer length?

getLength() - request. getOffset() + 1; The result of this is length = 20 as size was 15. That is, request.

What is Java NIO ByteBuffer?

A ByteBuffer is a buffer which provides for transferring bytes from a source to a destination. In addition to storage like a buffer array, it also provides abstractions such as current position, limit, capacity, etc. A FileChannel is used for transferring data to and from a file to a ByteBuffer.

How does ByteBuffer work in Java?

ByteBuffer holds a sequence of integer values to be used in an I/O operation. The ByteBuffer class provides the following four categories of operations upon long buffers: Absolute and relative get method that read single bytes. Absolute and relative put methods that write single bytes.


3 Answers

You should be able to use ByteBuf.nioBuffers(). Which will return a view of the ByteBuf as an array of ByteBuffer objects.

In most cases this array will only have one element, but in some of the more complicated implementations of ByteBuf there may be multiple underlying ByteBuffer objects and ByteBuf.nioBuffers() can return them as-is instead of merging them as would a call to ByteBuf.nioBuffer().

You can tell ahead of time what the array length will be by using ByteBuf.nioBufferCount()

like image 177
Dev Avatar answered Nov 09 '22 08:11

Dev


You can at least use ByteBuffer.wrap() to avoid the second copying.

like image 24
Kayaman Avatar answered Nov 09 '22 08:11

Kayaman


Not particularly efficient but doing the trick:

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);
}
like image 30
Hbf Avatar answered Nov 09 '22 08:11

Hbf