0% found this document useful (0 votes)
116 views

How To Read and Write Binary Files in Java

The document discusses how to read and write binary files in Java using both legacy File I/O API and new File I/O API (NIO). It provides examples of using FileInputStream, FileOutputStream, BufferedInputStream and BufferedOutputStream to read and write binary files one byte at a time, the whole file at once, or in chunks. It also demonstrates how to check the file format of a binary file by reading the first few bytes and comparing with a signature.

Uploaded by

ravi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
116 views

How To Read and Write Binary Files in Java

The document discusses how to read and write binary files in Java using both legacy File I/O API and new File I/O API (NIO). It provides examples of using FileInputStream, FileOutputStream, BufferedInputStream and BufferedOutputStream to read and write binary files one byte at a time, the whole file at once, or in chunks. It also demonstrates how to check the file format of a binary file by reading the first few bytes and comparing with a signature.

Uploaded by

ravi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

How to Read and Write Binary Files in Java

codejava.net/java-se/file-io/how-to-read-and-write-binary-files-in-java

Written by Nam Ha Minh


Last Updated on 28 July 2019 | Print Email

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:

1/12
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

2/12
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:

1 import java.io.*;

2 /**

3 * Copy one file to another using low level byte streams, one byte
at a time.
4
* @author www.codejava.net
5 */
6
public class CopyFiles {
7 public static void main(String[] args) {
8
if (args.length < 2 ) {
9 System.out.println( "Please provide input and output files" );
10 System.exit( 0 );

11 }

12 String inputFile = args[ 0 ];

13 String outputFile = args[ 1 ];

14 try (

15 InputStream inputStream = new FileInputStream(inputFile);

16 OutputStream outputStream = new FileOutputStream(outputFile);

17 ) {

18 int byteRead;

19 while ((byteRead = inputStream.read()) != - 1 ) {

20 outputStream.write(byteRead);

}
21
} catch (IOException ex) {
22
ex.printStackTrace();
23
}

3/12
24 }

25 }

26

27

28

29

30

31

32

33

Run this program like this:

1 java CopyFiles Project.zip Project1(1).zip

This program runs very slow because it copies exactly one byte at a time. 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:

1 import java.io.*;

2 /**

3 * Copy one file to another using low level byte streams,

4 * read and write a whole.at once.

* @author www.codejava.net
5
*/
6
public class CopyFilesOne {
7
public static void main(String[] args) {
8
if (args.length < 2 ) {
9
System.out.println( "Please provide input and output files" );
10
System.exit( 0 );
11
}
12
String inputFile = args[ 0 ];
13
String outputFile = args[ 1 ];

4/12
14 try (

15 InputStream inputStream = new FileInputStream(inputFile);

16 OutputStream outputStream = new FileOutputStream(outputFile);

17 ) {

18 long fileSize = new File(inputFile).length();

19 byte [] allBytes = new byte [( int ) fileSize];

20 inputStream.read(allBytes);

21 outputStream.write(allBytes);

22 } catch (IOException ex) {

ex.printStackTrace();
23
}
24
}
25
}
26

27

28

29

30

31

32

33

34

35

36

37

And the following program runs much faster by copying a chunk of bytes at a time
(exactly 4096 bytes at a time):

1 import java.io.*;

2 /**

3 * Copy one file to another using low level byte streams, 4KB at a
time.

5/12
4 * @author www.codejava.net

5 */

6 public class CopyFilesChunk {

7 private static final int BUFFER_SIZE = 4096 ; // 4KB

8 public static void main(String[] args) {

9 if (args.length < 2 ) {

10 System.out.println( "Please provide input and output files" );

System.exit( 0 );
11
}
12
String inputFile = args[ 0 ];
13
String outputFile = args[ 1 ];
14
try (
15
InputStream inputStream = new FileInputStream(inputFile);
16
OutputStream outputStream = new FileOutputStream(outputFile);
17
) {
18
byte [] buffer = new byte [BUFFER_SIZE];
19
while (inputStream.read(buffer) != - 1 ) {
20
outputStream.write(buffer);
21
}
22
} catch (IOException ex) {
23
ex.printStackTrace();
24
}
25 }
26 }
27

28

29

30

31

32

33

6/12
34

35

The following program reads the first 8 bytes of a file to identify if it is a PNG image
format or not:

1 import java.io.*;

2 /**

3 * This program checks whether a file is of PNG image format or


not,
4
* by analysing its first 8 bytes.
5 * @author www.codejava.net
6 */
7 public class CheckPNG {
8 private static int [] pngSignature = { 137 , 80 , 78 ,
71 , 13 , 10 , 26 , 10 };
9
public static void main(String[] args) {
10
if (args.length < 1 ) {
11
System.out.println( "Please provide the input file" );
12
System.exit( 0 );
13
}
14
String inputFile = args[ 0 ];
15
try (
16
InputStream inputStream = new FileInputStream(inputFile);
17
) {
18
int [] headerBytes = new int [ 8 ];
19
boolean isPNG = true ;
20
for ( int i = 0 ; i < 8 ; i++) {
21
headerBytes[i] = inputStream.read();
22
if (headerBytes[i] != pngSignature[i]) {
23 isPNG = false ;
24 break ;
25 }

7/12
26 }

27 System.out.println( "Is PNG file? " + isPNG);

28 } catch (IOException ex) {

29 ex.printStackTrace();

30 }

}
31
}
32

33

34

35

36

37

38

39

40

41

42

Run this program like this:

1 java CheckPNG Diagram.png

If the file is really a PNG image, it prints the output: Is PNG file? trueAs 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

8/12
examples can be re-written using buffered streams just by changing the instantiation of
the streams. Here’s an example:

1 try (

2 InputStream inputStream = new BufferedInputStream( new


FileInputStream(inputFile));
3
OutputStream outputStream = new BufferedOutputStream( new
4 FileOutputStream(outputFile));

5 ) {

6 byte [] buffer = new byte [BUFFER_SIZE];

7 while (inputStream.read(buffer) != - 1 ) {

8 outputStream.write(buffer);

}
9
} catch (IOException ex) {
10
ex.printStackTrace();
11
}
12

13

14

And we can specify a custom size for the buffer like this:

1 int bufferSize = 16384 ; // 16KB buffer size

2 InputStream inputStream

3 = new BufferedInputStream( new FileInputStream(inputFile),


bufferSize);
4
OutputStream outputStream
5
= new BufferedOutputStream( new FileOutputStream(outputFile),
6 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:

9/12
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.

Note that both methods close the input and output file after done and throw
IOException in case of error.Let’s see an example. The files copy program above can be
re-written using NIO API like this:

1 import java.io.*;

2 import java.nio.file.*;

3 /**

4 * Copy one file to another using low level byte streams, one byte
at a time.
5
* @author www.codejava.net
6 */
7 public class CopyFilesNIO {
8 public static void main(String[] args) {
9 if (args.length < 2 ) {
10 System.out.println( "Please provide input and output files" );
11 System.exit( 0 );

12 }

13 String inputFile = args[ 0 ];

14 String outputFile = args[ 1 ];

15 try {

16 long start = System.currentTimeMillis();

17 byte [] allBytes = Files.readAllBytes(Paths.get(inputFile));

18 Files.write(Paths.get(outputFile), allBytes);

19 long end = System.currentTimeMillis();

20 System.out.println( "Copied in " + (end - start) + " ms" );

21 } catch (IOException ex) {

ex.printStackTrace();
22
}
23
}

10/12
24 }

25

26

27

28

29

30

31

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.

JavaBinaryFileIOExamples.zip [Java Binary File IO Examples] 4 kB

Attachments:

Add comment

Comments

11/12
#2Adrian Gibanel bTact2019-10-08 04:34

The program: "And the following program runs much faster by copying a chunk of bytes
at a time (exactly 4096 bytes at a time):" when inputed a 169KB size file it outputs a
172KB size file.

It doesn't seem a very accurate way of copying a file.

It would very nice if you could take into account that not every file size is a 4096 multiple.

Thank you.
Quote
#1Vishnu Prathap2018-11-25 22:27
Very helpfull and usefull

Quote
Refresh comments list

12/12

You might also like