31

How to get a byte array from ByteBuf efficiently in the code below? I need to get the array and then serialize it.

package testingNetty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class ServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { System.out.println("Message receive"); ByteBuf buff = (ByteBuf) msg; // There is I need get bytes from buff and make serialization byte[] bytes = BuffConvertor.GetBytes(buff); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // Close the connection when an exception is raised. cause.printStackTrace(); ctx.close(); } } 
4
  • Can you please post the complete code. Also mention the which version of netty you are using? Commented Oct 10, 2013 at 13:12
  • I use 4.0.9 version of Netty Commented Oct 10, 2013 at 13:16
  • So what's problem is? What do you mean by bytes massive in the above context? Commented Oct 10, 2013 at 13:35
  • Bytes massive means a byte[] wich contains seriziable object Commented Oct 10, 2013 at 14:12

2 Answers 2

91
ByteBuf buf = ... byte[] bytes = new byte[buf.readableBytes()]; buf.readBytes(bytes); 

If you don't want the readerIndex to change:

ByteBuf buf = ... byte[] bytes = new byte[buf.readableBytes()]; int readerIndex = buf.readerIndex(); buf.getBytes(readerIndex, bytes); 

If you want to minimize the memory copy, you can use the backing array of the ByteBuf, if it's available:

ByteBuf buf = ... byte[] bytes; int offset; int length = buf.readableBytes(); if (buf.hasArray()) { bytes = buf.array(); offset = buf.arrayOffset(); } else { bytes = new byte[length]; buf.getBytes(buf.readerIndex(), bytes); offset = 0; } 

Please note that you can't simply use buf.array(), because:

  • Not all ByteBufs have backing array. Some are off-heap buffers (i.e. direct memory)
  • Even if a ByteBuf has a backing array (i.e. buf.hasArray() returns true), the following isn't necessarily true because the buffer might be a slice of other buffer or a pooled buffer:
    • buf.array()[0] == buf.getByte(0)
    • buf.array().length == buf.capacity()
Sign up to request clarification or add additional context in comments.

8 Comments

@user2132106 would like to know if he can do byte[] ar= buf.array() (if I understand the post correctly).
Updated the answer for him.
@trustin what's the purpose of the offset here?
I tested with real data: the second way (minimize the memory copy) is wrong. Java platform: Oracle 1.8; netty version: 4.1.58.Final.
@Fireburn offset tells at which position in the array the first byte starts.
|
6

Another option is ByteBufUtil.getBytes(ByteBuf buf, int start, int length, boolean copy)

See ByteBufUtil

2 Comments

There is indeed an option to share the array instead of copying it (if possible)
Thanks @TuomasKiviaho . I updated my answer per your comment.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.