- 7 Examples to Read File into a byte array in Java
- 7 ways to read a file into a byte array in Java
- 1) Using Apache Commons IOUtils
- 2) Using Apache Commons FileUtils
- 3) Using FileInputStream and JDK
- Read File to Byte[] in Java
- How to Read and Write Binary Files in Java
- 1. Understanding Byte Streams
- 2. Reading and Writing Binary Files Using FileInputStream and FileOutputStream
- 3. Reading and Writing Binary Files Using BufferedInputStream and BufferedOutputStream
- 4. Reading and Writing Binary Files Using New File I/O API (NIO)
- API References:
- Related File IO Tutorials:
- Other Java File IO Tutorials:
- About the Author:
7 Examples to Read File into a byte array in Java
Hello guys, Java programmers often face scenarios in real-world programming, where they need to load data from a file into a byte array, it could be text or binary file. One example is to convert the contents of a file into String for display. Unfortunately, Java’s File class, which is used to represent both files and directories, doesn’t have a method say toByteArray() . It only holds path and allows you to perform certain operations like opening and closing file, but doesn’t allow you to directly convert File to a byte array. Anyway, no need to worry as there are several other ways to read File into a byte array and you will learn those in this Java file tutorial.
If you are a fan of Apache commons and Google Guava like me, then you may already familiar with one-liner code, which can quickly read a file into a byte array; if not, then this is the right time to explore those API. In this tutorial, we are going to see 7 different examples to read File to a byte array, some by using third party libraries, and others by using JDK 6 and JDK 7 core Java libs. Depending upon your choice, you can use any of the following methods to convert file data into bytes. One thing to keep in mind is what you are doing with byte array; if you are creating String from a byte array, then beware with character encoding. You may need to find out correct character encoding by reading metadata information like Content-Type of HTML pages and of XML documents. While reading XML documents, it’s a bad idea to first read an XML file and store it in a String. Instead, it’s better to pass InputStream to XML parsers, and they will figure out the encoding themselves correctly.
One more thing to note is that you cannot read file larger than 2GB into a single byte array, you need multiple byte arrays for that. This limitation comes from the fact that the array index in Java is of int type, whose maximum value is 2147483647 , roughly equivalent to 2GB. Btw, I am expecting that you are familiar with basic Java Programing and Java API in general.
7 ways to read a file into a byte array in Java
Without wasting any more of your time, here are all the seven ways to load a file into a byte array in Java:
1) Using Apache Commons IOUtils
This is one of the easiest ways to read a file data into a byte array, provided you don’t hate third-party libraries. It’s productive because you don’t need to code it from scratch, worrying about exception handling, etc.
The IOUtils.toByteArray(InputStream input) Gets the contents of an
InputStream as a byte[]. This method also buffers the input internally, so there is no need to use a BufferedInputStream , but it’s not null-safe. It throws NullPointerException if the input is null .
2) Using Apache Commons FileUtils
The FileUtils class from org.apache.commons.io package provides a general file manipulation facility like writing to a file or reading from a file. This method is used to read the contents of a file into a byte array, and the good thing about this is that the file is always closed.
3) Using FileInputStream and JDK
This is the classic way of reading the file’s content into a byte array. Don’t forget to close the stream once done. Here is the code to read a file into a byte array using FileInputStream class in Java:
Read File to Byte[] in Java
In Java, reading a file to byte array may be needed in various situations. For example, passing the information through the network and other APIs for further processing.
Let’s learn about a few ways of reading data from files into a byte array in Java.
1. Using Files.readAllBytes()
The Files.readAllBytes() is the best method for using Java 7, 8 and above. It reads all bytes from a file and closes the file. The file is also closed on an I/O error or another runtime exception is thrown.
This method read all bytes into memory in a single statement so do not use it to read large files, else you may face OutOfMemoryError.
Path path = Paths.get("C:/temp/test.txt"); byte[] data = Files.readAllBytes(path);
Use FileInputStream for reading the content of a file when you already have the InputStream reference. Don’t forget to close the stream once the reading is done; else use try-with-resources block.
File file = new File("C:/temp/test.txt"); byte[] bytes = new byte[(int) file.length()]; try(FileInputStream fis = new FileInputStream(file))
3. Using Apache Commons IO
Another good way to read data into a byte array is in the apache commons IO library. It provides several useful classes for dealing with IO operations.
In the following example, we are using the FileUtils class to read the file content into byte array. The file is always closed either success or read error.
byte[] bytes = FileUtils.readFileToByteArray(file);
A similar class is IOUtils which can be used in the same way.
byte[] bytes = IOUtils.toByteArray(new FileInputStream(file));
Another good way to read data into a byte array is in Google Guava library.
The following example uses the com.google.common.io.Files class to read the file content into a byte array.
byte[] bytes3 = com.google.common.io.Files.toByteArray(file);
How to Read and Write Binary Files in Java
In this Java File IO tutorial, we show you how to read and write binary files using both legacy File I/O API and new File I/O API (NIO). The legacy API (classes in the java.io.* package) is perfect for manipulating low-level binary I/O operations such as reading and writing exactly one byte at a time, whereas the NIO API (classes in the java.nio.* package) is more convenient for reading and writing the whole file at once, and of course, faster than the old File I/O API.
1. Understanding Byte Streams
We use byte streams to read and write data in binary format, exactly 8-bit bytes. All byte stream classes are descended from the abstract classes InputStream and OutputStream . The following class diagram depicts the main classes in the legacy File I/O API that are designed for working with binary files:
You can notice that these classes implement the AutoCloseable interface, which means that we can use the try-with-resources structure to close these streams automatically.
At the top of the hierarchy, the abstract class InputStream defines two primary methods for reading bytes from an input stream:
- read() : reads one byte of data, returns the byte as an integer value. Return -1 if the end of the file is reached.
- read(byte[]) : reads a chunk of bytes to the specified byte array, up to the size of the array. This method returns -1 if there’s no more data or the end of the file is reached.
Similarly, the abstract class OutputStream defines two primary methods for writing bytes to an output stream:
- write(int) : writes the specified byte to the output stream.
- write(byte[]) : writes the specified array of bytes to the output stream.
Moving down, the implementation classes FileInputStream and FileOutputStream are for reading and writing streams of raw bytes, one or multiple bytes at a time. Whereas the BufferedInputStream and BufferedOutputStream are more efficient by buffering the input stream and output stream to reduce the number of calls to the native API.
Now, let’s see some code examples.
2. Reading and Writing Binary Files Using FileInputStream and FileOutputStream
The following examples use the FileInputStream and FileOutputStream classes to perform low level binary I/O.
This program copies one file to another, one byte at a time. The source file and destination file are provided from command line’s arguments:
import java.io.*; /** * Copy one file to another using low level byte streams, one byte at a time. * @author www.codejava.net */ public class CopyFiles < public static void main(String[] args) < if (args.length < 2) < System.out.println("Please provide input and output files"); System.exit(0); >String inputFile = args[0]; String outputFile = args[1]; try ( InputStream inputStream = new FileInputStream(inputFile); OutputStream outputStream = new FileOutputStream(outputFile); ) < int byteRead = -1; while ((byteRead = inputStream.read()) != -1) < outputStream.write(byteRead); >> catch (IOException ex) < ex.printStackTrace(); >> >
java CopyFiles Project.zip Project1(1).zip
And the following program runs faster because it reads the whole input file into an array of bytes and then write the whole array of bytes to the output file:
import java.io.*; /** * Copy one file to another using low level byte streams, * read and write a whole.at once. * @author www.codejava.net */ public class CopyFilesOne < public static void main(String[] args) < if (args.length < 2) < System.out.println("Please provide input and output files"); System.exit(0); >String inputFile = args[0]; String outputFile = args[1]; try ( InputStream inputStream = new FileInputStream(inputFile); OutputStream outputStream = new FileOutputStream(outputFile); ) < long fileSize = new File(inputFile).length(); byte[] allBytes = new byte[(int) fileSize]; int bytesRead = inputStream.read(allBytes); outputStream.write(allBytes, 0, bytesRead); >catch (IOException ex) < ex.printStackTrace(); >> >
And the following program runs much faster by copying a chunk of bytes at a time (exactly 4096 bytes at a time):
import java.io.*; /** * Copy one file to another using low level byte streams, 4KB at a time. * @author www.codejava.net */ public class CopyFilesChunk < private static final int BUFFER_SIZE = 4096; // 4KB public static void main(String[] args) < if (args.length < 2) < System.out.println("Please provide input and output files"); System.exit(0); >String inputFile = args[0]; String outputFile = args[1]; try ( InputStream inputStream = new FileInputStream(inputFile); OutputStream outputStream = new FileOutputStream(outputFile); ) < byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = -1; while ((bytesRead = inputStream.read(buffer)) != -1) < outputStream.write(buffer, 0, bytesRead); >> catch (IOException ex) < ex.printStackTrace(); >> >
The following program reads the first 8 bytes of a file to identify if it is a PNG image format or not:
import java.io.*; /** * This program checks whether a file is of PNG image format or not, * by analysing its first 8 bytes. * @author www.codejava.net */ public class CheckPNG < private static int[] pngSignature = ; public static void main(String[] args) < if (args.length < 1) < System.out.println("Please provide the input file"); System.exit(0); >String inputFile = args[0]; try ( InputStream inputStream = new FileInputStream(inputFile); ) < int[] headerBytes = new int[8]; boolean isPNG = true; for (int i = 0; i < 8; i++) < headerBytes[i] = inputStream.read(); if (headerBytes[i] != pngSignature[i]) < isPNG = false; break; >> System.out.println("Is PNG file? " + isPNG); > catch (IOException ex) < ex.printStackTrace(); >> >
As you can see, using FileInputStream and FileOutputStream is really good for low level binary I/O such as analyzing a file or even create your own file format.
3. Reading and Writing Binary Files Using BufferedInputStream and BufferedOutputStream
Using BufferedInputStream and BufferedOutputStream is as same as FileInputStream and FileOutputStream . The only difference is that a buffered stream uses an array of byte internally to buffer the input and output to reduce the number of calls to the native API, hence increasing IO performance.
By default, both BufferedInputStream and BufferedOutputStream has an internal buffer of 8192 bytes (8KB), but we can specify a custom buffer size at initialization.
All the above examples can be re-written using buffered streams just by changing the instantiation of the streams. Here’s an example:
try ( InputStream inputStream = new BufferedInputStream(new FileInputStream(inputFile)); OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile)); ) < byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = -1; while ((bytesRead = inputStream.read(buffer)) != -1) < outputStream.write(buffer, 0, bytesRead); >> catch (IOException ex)
int bufferSize = 16384; // 16KB buffer size InputStream inputStream = new BufferedInputStream(new FileInputStream(inputFile), bufferSize); OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile), bufferSize);
4. Reading and Writing Binary Files Using New File I/O API (NIO)
The utility class Files in the java.nio.file package provides the following methods for reading and writing binary data:
- readAllBytes(Path path) : reads all bytes from a file and returns an array of bytes. This method is intended for reading small files, not large ones.
- write(Path path, byte[] bytes, OpenOption. options) : writes an array of bytes to a file with some useful options like CREATE, TRUNCATE_EXISTING, WRITE and APPEND.
Let’s see an example. The files copy program above can be re-written using NIO API like this:
import java.io.*; import java.nio.file.*; /** * Copy one file to another using low level byte streams, one byte at a time. * @author www.codejava.net */ public class CopyFilesNIO < public static void main(String[] args) < if (args.length < 2) < System.out.println("Please provide input and output files"); System.exit(0); >String inputFile = args[0]; String outputFile = args[1]; try < long start = System.currentTimeMillis(); byte[] allBytes = Files.readAllBytes(Paths.get(inputFile)); Files.write(Paths.get(outputFile), allBytes); long end = System.currentTimeMillis(); System.out.println("Copied in " + (end - start) + " ms"); >catch (IOException ex) < ex.printStackTrace(); >> >
Try to run this program and compare the time with the ones using legacy File I/O (on big files) you will see NIO performs much faster.
API References:
Related File IO Tutorials:
Other Java File IO Tutorials:
About the Author:
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.