 Java, Spring and Web Development tutorials  1. Overview
In this tutorial, we’ll shed light on how to convert between ByteBuffer and Byte arrays in Java. Understanding how to convert between these two formats is essential for tasks such as file I/O handling and network communication.
We’ll look at different methods for converting a ByteBuffer to a Byte[] and vice versa, then we’ll discuss when to use each approach.
2. Converting ByteBuffer to Byte Array
In Java, ByteBuffer is a core class from the java.nio package. It’s introduced to handle binary data in an efficient way. This is why it’s widely used in I/O operations.
First, let’s start by exploring how we can extract a Byte array from a ByteBuffer.
2.1. Using ByteBuffer.array()
The simplest and most straightforward option is to use the array() method. Typically, this method returns the byte array that backs the buffer:
@Test
void whenUsingArrayMethod_thenConvertToByteArray() {
byte[] givenBytes = {1, 6, 3};
ByteBuffer buffer = ByteBuffer.wrap(givenBytes);
byte[] bytes = buffer.array();
assertArrayEquals(givenBytes, bytes);
}
An important caveat here is that the array() method only works when the buffer has an accessible backing array. Otherwise, it throws UnsupportedOperationException:
@Test
void givenBufferWithoutBackingArray_whenCallingArray_thenThrowUnsupportedOperationException() {
ByteBuffer buffer = ByteBuffer.allocateDirect(4);
assertThrows(UnsupportedOperationException.class, buffer::array);
}
It’s always safer to check whether the buffer has a backing array using the hasArray() method before calling array(). It acts as a guard to prevent UnsupportedOperationException.
Please note also that the array() method throws ReadOnlyBufferException if the buffer is read-only:
@Test
void givenReadOnlyBuffer_whenCallingArray_thenThrowReadOnlyBufferException() {
ByteBuffer buffer = ByteBuffer.wrap(new byte[] {1, 2, 3});
ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();
assertThrows(ReadOnlyBufferException.class, readOnlyBuffer::array);
}
As we can see, the array() method fails with a ReadOnlyBufferException.
2.2. Using ByteBuffer.get()
Alternatively, we can use the get() method. It offers a more robust and flexible approach to extract a Byte array:
@Test
void whenUsingGetMethod_thenConvertToByteArray() {
byte[] givenBytes = {5, 4, 2};
ByteBuffer buffer = ByteBuffer.wrap(givenBytes);
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
assertArrayEquals(givenBytes, bytes);
}
This method creates a new copy of the buffer’s data, which guarantees independence between the buffer and the returned byte array.
Please note that we can specify an offset and a length for more precise control over how data is copied from the buffer:
@Test
void givenByteBuffer_whenUsingGetWithParamsMethod_thenConvertToByteArray() {
byte[] givenBytes = {5, 4, 2, 7};
ByteBuffer buffer = ByteBuffer.wrap(givenBytes);
byte[] bytes = new byte[2];
buffer.get(bytes, 0, 2);
assertArrayEquals(new byte[] {5, 4}, bytes);
}
Here, the destination array contains only 2 elements, matching the number of copied bytes.
3. Converting Byte Array to ByteBuffer
Now, let’s go down the rabbit hole and see how to create a ByteBuffer from a byte array.
3.1. Using ByteBuffer.wrap()
The most common approach is using the method wrap(). As the name implies, it wraps a given byte array into a buffer:
@Test
void whenUsingWrapMethod_thenConvertToByteBuffer() {
byte[] givenBytes = {1, 2, 3};
ByteBuffer buffer = ByteBuffer.wrap(givenBytes);
assertArrayEquals(givenBytes, buffer.array());
}
Notably, this method creates a buffer that directly uses the provided array as its backing storage. So, any change to the buffer will be reflected in the array and vice versa.
ByteBuffer also provides wrap(array, offset, length). However, instead of creating a new array starting at the offset, it wraps the entire original array and sets the position to the given offset:
@Test
void givenByteArray_whenUsingWrapWithParamsMethod_thenConvertToByteBuffer() {
byte[] givenBytes = {1, 2, 3, 7, 8};
ByteBuffer buffer = ByteBuffer.wrap(givenBytes, 1, 2);
byte[] actualBytes = new byte[buffer.remaining()];
buffer.get(actualBytes);
assertArrayEquals(new byte[] {2, 3}, actualBytes);
}
As shown above, we used get() to return the slice because the wrap(array, offset, length) method doesn’t control the underlying array.
3.2. Using ByteBuffer.allocate()
Similarly, we can use the allocate() method to convert a byte array to a ByteBuffer. We should use it combined with put():
@Test
void whenUsingAllocateAndPutMethods_thenConvertToByteBuffer() {
byte[] givenBytes = {1, 9, 7};
ByteBuffer buffer = ByteBuffer.allocate(givenBytes.length);
buffer.put(givenBytes);
assertArrayEquals(givenBytes, buffer.array());
}
In a nutshell, this approach allocates a new buffer and copies the data, which creates complete independence between the buffer and the original array.
However, the buffer position moves to the end after writing with put(). So, we need to call flip() to reset the buffer:
@Test
void givenByteArray_whenUsingPutWithFlip_thenReadWithoutException() {
byte[] givenBytes = {3, 8};
ByteBuffer buffer = ByteBuffer.allocate(givenBytes.length);
buffer.put(givenBytes);
buffer.flip();
assertEquals(3, buffer.get());
}
Otherwise, reading from the buffer using the get() method may lead to a BufferUnderflowException:
@Test
void givenByteArray_whenUsingPutWithoutFlip_thenThrowBufferUnderflowException() {
byte[] givenBytes = {1, 5};
ByteBuffer buffer = ByteBuffer.allocate(givenBytes.length);
buffer.put(givenBytes);
assertThrows(BufferUnderflowException.class, buffer::get);
}
As expected, the test case confirms that the get() method throws BufferUnderflowException if we don’t use flip() to reset the buffer position.
4. Conclusion
In this article, we explored various methods for converting between ByteBuffer and byte arrays in Java.
The full source is available over on GitHub. The post Convert Between ByteBuffer and Byte Array in Java first appeared on Baeldung.
Content mobilized by FeedBlitz RSS Services, the premium FeedBurner alternative. |