Java InputStream to Byte Array and ByteBuffer

1. Overview

In this quick tutorial, we’re going to take a look at how to convert an InputStream to a byte[] and ByteBuffer – first using plain Java, then using Guava and Commons IO.

This article is part of the “Java – Back to Basic” series here on VietMX’s Blog.

2. Convert to Byte Array

Let’s look at obtaining a byte array from simple input streamsThe important aspect of a byte array is that it enables an indexed (fast) access to each 8-bit (a byte) value stored in memory. Hence, you can manipulate these bytes to control each bit. We are going to take a look at how to convert a simple input stream to a byte[] – first using plain Java, then using Guava and Apache Commons IO.

2.1. Convert Using Plain Java

Let’s start with a Java solution focused on dealing with a fixed size stream:

@Test
public void givenUsingPlainJavaOnFixedSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() 
  throws IOException {
    InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2 });
    byte[] targetArray = new byte[is.available()];

    is.read(targetArray);
}

In the case of a buffered stream – where we’re dealing with a buffered stream and don’t know the exact size of the underlying data, we need to make the implementation more flexible:

@Test
public void givenUsingPlainJavaOnUnknownSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() 
  throws IOException {
    InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4, 5, 6 }); // not really known
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    int nRead;
    byte[] data = new byte[4];

    while ((nRead = is.read(data, 0, data.length)) != -1) {
        buffer.write(data, 0, nRead);
    }

    buffer.flush();
    byte[] targetArray = buffer.toByteArray();
}

Starting with Java 9, we can achieve the same with a dedicated readNbytes method:

@Test
public void givenUsingPlainJava9OnUnknownSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() 
  throws IOException {
    InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4, 5, 6 });
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    int nRead;
    byte[] data = new byte[4];

    while ((nRead = is.readNBytes(data, 0, data.length)) != 0) {
        System.out.println("here " + nRead);
        buffer.write(data, 0, nRead);
    }

    buffer.flush();
    byte[] targetArray = buffer.toByteArray();
}

The difference between these two methods is very subtle.

The first one, read​(byte[] b, int off, int len), reads up to len bytes of data from the input stream, whereas the second one, readNBytes​(byte[] b, int off, int len), reads exactly the requested number of bytes.

Additionally, read returns -1 if there’s no more data available in the input stream. readNbytes, however, always returns the actual number of bytes read into the buffer.

We can also read all the bytes at once:

@Test
public void
  givenUsingPlainJava9_whenConvertingAnInputStreamToAByteArray_thenCorrect()
  throws IOException {
    InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2 });

    byte[] data = is.readAllBytes();
}

2.2. Convert Using Guava

Let’s now look at the simple Guava based solution – using the convenient ByteStreams utility class:

@Test
public void givenUsingGuava_whenConvertingAnInputStreamToAByteArray_thenCorrect() 
  throws IOException {
    InputStream initialStream = ByteSource.wrap(new byte[] { 0, 1, 2 }).openStream();
    
    byte[] targetArray = ByteStreams.toByteArray(initialStream);
}

2.3. Convert Using Commons IO

And finally – a straightforward solution using Apache Commons IO:

@Test
public void givenUsingCommonsIO_whenConvertingAnInputStreamToAByteArray_thenCorrect() 
  throws IOException {
    ByteArrayInputStream initialStream = new ByteArrayInputStream(new byte[] { 0, 1, 2 });
    
    byte[] targetArray = IOUtils.toByteArray(initialStream);
}

The method IOUtils.toByteArray() buffers the input internally, so there is no need to use a BufferedInputStream instance when buffering is needed.

3. Convert to ByteBuffer

Now, let’s look at obtaining a ByteBuffer from an InputStream. This is useful whenever we need to do fast and direct low-level I/O operations in memory.

Using the same approach as the above sections, we’re going to take a look at how to convert an InputStream to a ByteBuffer – first using plain Java, then using Guava and Commons IO.

3.1. Convert Using Plain Java

In the case of a byte stream – we know the exact size of the underlying data. Let’s use the ByteArrayInputStream#available method to read the byte stream into a ByteBuffer:

@Test
public void givenUsingCoreClasses_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() 
  throws IOException {
    byte[] input = new byte[] { 0, 1, 2 };
    InputStream initialStream = new ByteArrayInputStream(input);
    ByteBuffer byteBuffer = ByteBuffer.allocate(3);
    while (initialStream.available() > 0) {
        byteBuffer.put((byte) initialStream.read());
    }

    assertEquals(byteBuffer.position(), input.length);
}

3.2. Convert Using Guava

Let’s now look at a simple Guava-based solution – using the convenient ByteStreams utility class:

@Test
public void givenUsingGuava__whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() 
  throws IOException {
    InputStream initialStream = ByteSource
      .wrap(new byte[] { 0, 1, 2 })
      .openStream();
    byte[] targetArray = ByteStreams.toByteArray(initialStream);
    ByteBuffer bufferByte = ByteBuffer.wrap(targetArray);
    while (bufferByte.hasRemaining()) {
        bufferByte.get();
    }

    assertEquals(bufferByte.position(), targetArray.length);
}

Here we use a while loop with the method hasRemaining to show a different way to read all the bytes into the ByteBuffer. Otherwise, the assertion would fail because the ByteBuffer index position will be zero.

3.3. Convert Using Commons IO

And finally – using Apache Commons IO and the IOUtils class:

@Test
public void givenUsingCommonsIo_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() 
  throws IOException {
    byte[] input = new byte[] { 0, 1, 2 };
    InputStream initialStream = new ByteArrayInputStream(input);
    ByteBuffer byteBuffer = ByteBuffer.allocate(3);
    ReadableByteChannel channel = newChannel(initialStream);
    IOUtils.readFully(channel, byteBuffer);

    assertEquals(byteBuffer.position(), input.length);
}

4. Conclusion

This article illustrated various ways to convert a raw input stream to a byte array and a ByteBuffer using plain Java, Guava, and Apache Commons IO.

The implementation of all these examples can be found in our GitHub project.

Related posts:

Java Program to Perform Preorder Non-Recursive Traversal of a Given Binary Tree
Java Program to Implement Levenshtein Distance Computing Algorithm
Spring Cloud Series – The Gateway Pattern
Tìm hiểu về xác thực và phân quyền trong ứng dụng
Lớp Arrarys trong Java (Arrays Utility Class)
Java Program to Implement the Hungarian Algorithm for Bipartite Matching
Summing Numbers with Java Streams
How to Get All Spring-Managed Beans?
Debug a HttpURLConnection problem
Tiêu chuẩn coding trong Java (Coding Standards)
Spring @RequestMapping New Shortcut Annotations
Java Program to Give an Implementation of the Traditional Chinese Postman Problem
Running Spring Boot Applications With Minikube
Collect a Java Stream to an Immutable Collection
Show Hibernate/JPA SQL Statements from Spring Boot
Java Program to Find Minimum Number of Edges to Cut to make the Graph Disconnected
Jackson – Decide What Fields Get Serialized/Deserialized
Java Web Services – JAX-WS – SOAP
How to Replace Many if Statements in Java
Java Program to Implement Knight’s Tour Problem
Exception Handling in Java
Java Program to Check Whether an Undirected Graph Contains a Eulerian Cycle
Giới thiệu về Stream API trong Java 8
Derived Query Methods in Spring Data JPA Repositories
Java Program to Perform Search in a BST
Spring Security Form Login
A Quick Guide to Using Keycloak with Spring Boot
Java Program to Implement the MD5 Algorithm
Java Program to Implement LinkedBlockingDeque API
Guide to the Java Queue Interface
Setting the Java Version in Maven
Hướng dẫn sử dụng Printing Service trong Java