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 Baeldung.

2. Convert to Byte Array

Let’s look at obtaining a byte array from simple input streams*.* The 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.