115

Is this the recommended way to get the bytes from the ByteBuffer

ByteBuffer bb =..

byte[] b = new byte[bb.remaining()]
bb.get(b, 0, b.length);
Jonas
  • 121,568
  • 97
  • 310
  • 388
kal
  • 28,545
  • 49
  • 129
  • 149

6 Answers6

123

Depends what you want to do.

If what you want is to retrieve the bytes that are remaining (between position and limit), then what you have will work. You could also just do:

ByteBuffer bb =..

byte[] b = new byte[bb.remaining()];
bb.get(b);

which is equivalent as per the ByteBuffer javadocs.

Yves
  • 11,597
  • 17
  • 83
  • 180
Jason S
  • 184,598
  • 164
  • 608
  • 970
  • 6
    Correct. And note that `bb.capacity()` *might* equal `bb.remaining()` even when the backing array is longer, so you must not use their equality as a test of when `bb.array()` is correct. See `ByteBuffer.slice()`. – cdunn2001 Sep 26 '12 at 00:01
  • 1
    Note that, to avoid changing the position of the buffer, I used `bb.slice().remaining()`. That way it looks like a clean dump without touching the original buffer. – Kyll Jan 21 '17 at 14:09
  • this method gives me signed bytes however i want unsigned...any idea? – H Raval Apr 14 '17 at 11:04
  • Java doesn't have the notion of unsigned integers, only signed ones. If you want "unsigned bytes", you need to cast as `int` and use a bitmask: `int unsigned_byte = b[k] & 0xff;` for some value of `k`. – Jason S Apr 15 '17 at 02:13
  • If you want to get the entire buffer into a byte array, would you call `ByteBuffer#clear` first? – Kenny Worden Jun 08 '18 at 21:59
24

Note that the bb.array() doesn't honor the byte-buffers position, and might be even worse if the bytebuffer you are working on is a slice of some other buffer.

I.e.

byte[] test = "Hello World".getBytes("Latin1");
ByteBuffer b1 = ByteBuffer.wrap(test);
byte[] hello = new byte[6];
b1.get(hello); // "Hello "
ByteBuffer b2 = b1.slice(); // position = 0, string = "World"
byte[] tooLong = b2.array(); // Will NOT be "World", but will be "Hello World".
byte[] world = new byte[5];
b2.get(world); // world = "World"

Which might not be what you intend to do.

If you really do not want to copy the byte-array, a work-around could be to use the byte-buffer's arrayOffset() + remaining(), but this only works if the application supports index+length of the byte-buffers it needs.

Jon
  • 9,156
  • 9
  • 56
  • 73
R4zorax
  • 504
  • 3
  • 10
  • "bb.array() doesn't honor the byte-buffers position", can you provide us more details about this part. I understood the slice example but need more details about why bb.array() mess up – kkrishnaai May 22 '19 at 09:42
8

As simple as that

  private static byte[] getByteArrayFromByteBuffer(ByteBuffer byteBuffer) {
    byte[] bytesArray = new byte[byteBuffer.remaining()];
    byteBuffer.get(bytesArray, 0, bytesArray.length);
    return bytesArray;
}
Salman Nazir
  • 2,759
  • 2
  • 28
  • 42
  • This is an excellent answer. I confirm the same logic is used here: `java.nio.channels.Channels.WritableByteChannelImpl.write(ByteBuffer)`. Does anyone know if this answer has any special edge cases that will not work? – kevinarpe Sep 09 '21 at 12:22
4
final ByteBuffer buffer;
if (buffer.hasArray()) {
    final byte[] array = buffer.array();
    final int arrayOffset = buffer.arrayOffset();
    return Arrays.copyOfRange(array, arrayOffset + buffer.position(),
                              arrayOffset + buffer.limit());
}
// do something else
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
4

If one does not know anything about the internal state of the given (Direct)ByteBuffer and wants to retrieve the whole content of the buffer, this can be used:

ByteBuffer byteBuffer = ...;
byte[] data = new byte[byteBuffer.capacity()];
((ByteBuffer) byteBuffer.duplicate().clear()).get(data);
Tomáš Myšík
  • 309
  • 3
  • 5
1

This is a simple way to get a byte[], but part of the point of using a ByteBuffer is avoiding having to create a byte[]. Perhaps you can get whatever you wanted to get from the byte[] directly from the ByteBuffer.

double-beep
  • 5,031
  • 17
  • 33
  • 41
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 17
    But often you'll need to call something (not in your own code) that takes a byte[], so converting isn't optional. – James Moore Mar 16 '11 at 14:55