Explain Codes LogoExplain Codes Logo

Convert InputStream to byte array in Java

java
io-utilities
stream-handling
performance-optimization
Nikita BarsukovbyNikita Barsukov·Aug 29, 2024
TLDR

To InputStream to a byte array in Java, java.io.ByteArrayOutputStream is your friend. Here's how:

// Prep a buffer because we're about to do some heavy lifting! ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int bytesRead; // Pump up the volume, or buffer size in our case! byte[] data = new byte[4096]; while ((bytesRead = inputStream.read(data)) != -1) { buffer.write(data, 0, bytesRead); // Get in there! } byte[] byteArray = buffer.toByteArray(); // Stage exit, stream bytes!

InputStream loads data chunks and ByteArrayOutputStream beautifully discards the unnecessary bits allowing you to fetch the byte array via its very own toByteArray() method, all without using a third-party library.

Quick library options

Sometimes you may need Jenny on the block, or simply a library, to do things more efficiently and with less code. Here're options:

  • Apache Commons IO: IOUtils.toByteArray(InputStream) reduces conversion to a one-line affair, streamlines reading with optimal speed for large files.

    // When you're too lazy to write it out yourself byte[] byteArray = IOUtils.toByteArray(inputStream);
  • Google Guava: ByteStreams.toByteArray(inputStream) ensures complete data capture for streams of unknown size and possibly saves from a disastrous IndexOutOfBounds nightmare.

    // Google always has the solution... byte[] byteArray = ByteStreams.toByteArray(inputStream);

Such libraries not only jazz up your code but also up your game in maintainability and performance.

Understanding your adversary: the stream size

Consideration for stream size should be given as much thought as for your next vacation spot:

  • The Mystery size: ByteArrayOutputStream internally expands for ambiguous stream lengths. Dynamic buffers can save you from an abrupt end-of-stream finale.
  • Perfomance: Think big to win big. A larger buffer, say 16KB or your lucky number, can reduce I/O operations thus upping efficiency.
  • The big bad file: Streams representing large files can be tricky. Java arrays can't exceed 2GiB. Hulk smash won't work here, have a plan for streams larger than 2 GiB.

New kid on the block: Java 9+ method

For folks running Java 9 or newer, InputStream.readAllBytes() offers an effortless way out:

// Finally, things get simpler! byte[] byteArray = inputStream.readAllBytes();

This method plays nice with InputStream by excluding an explicit read loop, while making code leaner. Works best with fixed-size streams on Java 9 or above.

Future-proof conversion technique

While creating solutions, ensure they're both all-weather ready and reusable:

  • Error handling: Wrapping things up with try-catch blocks is good. Ensuring IOExceptions don't ruin the party is even better!
  • Testing: Different stream sizes call for different handling. A routine test for this ensures you're ready for all of them.
  • Resource management: Whether using try-with-resources or manually closing streams the good old way, ensuring resources are freed post use ensures your program won't turn into Frankenstein.

When streams talk: stream-to-stream transfers

When you feel like passing on the byte stream directly to another stream:

  • Java 9 InputStream.transferTo(OutputStream) to the rescue. It's everyone's favorite smooth transfer facilitator, and it's efficient.

    // Running a relay race with streams inputStream.transferTo(outputStream);

Effective when the byte array is interim, and it saves memory and boosts performance. WIN-WIN!