1. Overview
In this quick tutorial, we’ll learn several different ways to write a Java byte array to a file. We’ll start at the beginning, using the Java IO package. Next, we’ll look at an example using Java NIO. Finally, we’ll use Google Guava and Apache Commons IO.
2. Java IO
Java’s IO package has been around since JDK 1.0, and provides a collection of classes and interfaces for reading and writing data.
Let’s use a FileOutputStream to write the image to a file:
File outputFile = tempFolder.newFile("outputFile.jpg");
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
outputStream.write(dataForWriting);
}
We’ll open an output stream to our destination file, and then we can simply pass our byte[] dataForWriting to the write method. Note that we’re using a try-with-resources block here to ensure that we close the OutputStream in case an IOException is thrown.
3. Java NIO
The Java NIO package was introduced in Java 1.4, and the file system API for NIO was introduced as an extension in Java 7. Java NIO uses buffering and is non-blocking, whereas Java IO uses blocking streams. The syntax for creating file resources is more succinct in the java.nio.file package.
We can write our byte[] in one line using the Files class:
Files.write(outputFile.toPath(), dataForWriting);
Our example either creates a file, or truncates an existing file and opens it for write. We can also use Paths.get(“path/to/file”) or Paths.get(“path”, “to”, “file”) to construct the Path that describes where our file will be stored. Path is the Java NIO native way of expressing paths.
If we need to override the file opening behavior, we can also provide OpenOption to the write method.
4. Google Guava
Guava is a library by Google that provides a variety of types for performing common operations in Java, including IO.
Let’s import Guava into our pom.xml file:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
4.1. Guava Files
As with the Java NIO package, we can write our byte[] in one line:
Files.write(dataForWriting, outputFile);
Guava’s Files.write method also takes an optional OptionOptions and uses the same defaults as java.nio.Files.write.
There’s a catch here though; the Guava Files.write method is marked with the @Beta annotation. According to the documentation, that means it can change at any time, and so isn’t recommended for use in libraries.
As such, if we’re writing a library project, we should consider using a ByteSink.
4.2. ByteSink
We can also create a ByteSink to write our byte[]:
ByteSink byteSink = Files.asByteSink(outputFile);
byteSink.write(dataForWriting);
The ByteSink is a destination to which we can write bytes. It supplies an OutputStream to the destination.
If we need to use a java.nio.files.Path or supply a special OpenOption, we can get our ByteSink using the MoreFiles class:
ByteSink byteSink = MoreFiles.asByteSink(outputFile.toPath(),
StandardOpenOption.CREATE,
StandardOpenOption.WRITE);
byteSink.write(dataForWriting);
5. Apache Commons IO
Apache Commons IO provides some common file tasks.
Let’s import the latest version of commons-io:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.15.1</version>
</dependency>
Now let’s write our byte[] using the FileUtils class:
FileUtils.writeByteArrayToFile(outputFile, dataForWriting);
The FileUtils.writeByteArrayToFile method is similar to the other methods that we’ve used in that we give it a File representing our desired destination and the binary data we’re writing. If our destination file or any of the parent directories don’t exist, they’ll be created.
6. Conclusion
In this brief article, we learned how to write binary data from a byte[] to a file using plain Java and two popular Java utility libraries, Google Guava and Apache Commons IO.
As always, the example code is available over on GitHub.