Chapter 17 Binary IO
Chapter 17 Binary IO
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 1
Motivations
Data stored in a text file is represented in human-readable
form. Data stored in a binary file is represented in binary
form. You cannot read binary files. They are designed to
be read by programs. For example, Java source programs
are stored in text files and can be read by a text editor, but
Java classes are stored in binary files and are read by the
JVM. The advantage of binary files is that they are more
efficient to process than text files.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 2
Objectives
To discover how I/O is processed in Java (§17.2).
To distinguish between text I/O and binary I/O (§17.3).
To read and write bytes using FileInputStream and FileOutputStream
(§17.4.1).
To read and write primitive values and strings using
DataInputStream/DataOutputStream (§17.4.3).
To store and restore objects using ObjectOutputStream and
ObjectInputStream, and to understand how objects are serialized and what
kind of objects can be serialized (§17.6).
To implement the Serializable interface to make objects serializable (§17.6.1).
To serialize arrays (§17.6.2).
To read and write the same file using the RandomAccessFile class (§17.7).
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 3
How is I/O Handled in Java?
A File object encapsulates the properties of a file or a path, but does not
contain the methods for reading/writing data from/to a file. In order to
perform I/O, you need to create objects using appropriate Java I/O classes.
Scanner input = new Scanner(new File("temp.txt"));
System.out.println(input.nextLine());
Program
Input stream
Input object
created from an 01011…1001 File
input class
Output object
created from an 11001…1011
File
output class
Output stream
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 5
Binary I/O
Text I/O requires encoding and decoding. The JVM converts a
Unicode to a file specific encoding when writing a character and
coverts a file specific encoding to a Unicode when reading a
character. Binary I/O does not require conversions. When you write
a byte to a file, the original byte is copied into the file. When you
read a byte from a file, the exact byte in the file is returned.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 6
Binary I/O Classes
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 7
Binary I/O Classes
All the methods in the binary I/O classes
are declared to throw java.io.IOException
or a subclass of java.io.IOException.
Therefore, you have to declare to throw
java.io.IOException in the method, or place
the code in a try-catch block.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 8
InputStream
The value returned is a byte as an int type.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 9
OutputStream
java.io.OutputStream
+write(int b): void Writes the specified byte to this output stream. The parameter b is an int value.
(byte)b is written to the output stream.
+write(b: byte[]): void Writes all the bytes in array b to the output stream.
+write(b: byte[], off: int, Writes b[off], b[off+1], …, b[off+len-1] into the output stream.
len: int): void
+close(): void Closes this output stream and releases any system resources associated with the
stream.
+flush(): void Flushes this output stream and forces any buffered output bytes to be written out.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 10
FileInputStream/FileOutputStream
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream
ObjectOutputStream PrintStream
FileInputStream/FileOutputStream associates a
binary input/output stream with an external file. All
the methods in FileInputStream/FileOuptputStream
are inherited from its superclasses.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 11
FileInputStream
To construct a FileInputStream, use the following
constructors:
public FileInputStream(String filename)
public FileInputStream(File file)
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 12
FileOutputStream
To construct a FileOutputStream, use the following constructors:
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 13
public class TestFileStream {
public static void main(String[] args) throws IOException {
try (
// Create an output stream to the file
FileOutputStream output = new FileOutputStream("temp.dat");
){
// Output values to the file
for (int i = 1; i <= 10; i++)
output.write(i);
try with
}
resources
try (
// Create an input stream for the file
FileInputStream input = new FileInputStream("temp.dat");
){
// Read values from the file
int value;
while ((value = input.read()) != -1)
System.out.print(value + " "); TestFileStream
}
}
}
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 14
FilterInputStream/FilterOutputStream
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream
ObjectOutputStream PrintStream
Filter streams are streams that filter bytes for some purpose. The basic byte input
stream provides a read method that can only be used for reading bytes. If you want to
read integers, doubles, or strings, you need a filter class to wrap the byte input stream.
Using a filter class enables you to read integers, doubles, and strings instead of bytes
and characters. FilterInputStream and FilterOutputStream are the base classes for
filtering data. When you need to process primitive numeric types, use DatInputStream
and DataOutputStream to filter bytes.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 15
DataInputStream/DataOutputStream
DataInputStream reads bytes from the stream
and converts them into appropriate primitive
type values or strings.
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream
ObjectOutputStream PrintStream
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 17
DataOutputStream
DataOutputStream extends FilterOutputStream and implements the
DataOutput interface.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 18
Characters and Strings in Binary I/O
A Unicode character consists of two bytes.
The writeChar(char c) method writes the Unicode of
character c to the output.
The writeChars(String s) method writes the Unicode for
each character in the string s to the output.
The writeBytes(String s) method writes the lower byte of
the Unicode for each character in the string s to the output.
The high byte of the Unicode is discarded.
– This method is suitable for strings that consisit of ASCII
characters, since an ASCII code is stored only in the lower byte of
a Unicode.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 19
Strings in Binary I/O
The readUTF() method reads a string using the UTF
format.
The writeUTF() method writes a string in the UTF format.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 20
Strings in Binary I/O
Since most applications need only the ASCII
character set, it is a waste to represent an 8-bit
ASCII character as a 16-bit Unicode character.
The UTF is an alternative scheme that stores a
character using 1, 2, or 3 bytes.
ASCII values (less than 0x7F) are coded in one
byte. Unicode values less than 0x7FF are coded in
two bytes. Other Unicode values are coded in
three bytes.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 21
Using DataInputStream/DataOutputStream
Data streams are used as wrappers on existing input and output
streams to filter data in the original stream. They are created using the
following constructors:
public DataInputStream(InputStream instream)
public DataOutputStream(OutputStream outstream)
The statements given below create data streams. The first statement
creates an input stream for file in.dat; the second statement creates an
output stream for file out.dat.
DataInputStream infile =
new DataInputStream(new FileInputStream("in.dat"));
DataOutputStream outfile =
new DataOutputStream(new FileOutputStream("out.dat"));
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 22
public class TestDataStream {
public static void main(String[] args) throws IOException {
try ( // Create an output stream for file temp.dat
DataOutputStream output =
new DataOutputStream(new FileOutputStream("temp.dat"));
){
// Write student test scores to the file
output.writeUTF("John");
output.writeDouble(85.5);
output.writeUTF("Jim");
output.writeDouble(185.5);
output.writeUTF("George");
output.writeDouble(105.25);
}
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 24
Using DataInputStream/DataOutputStream
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 25
Concept of pipe line
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 26
Order and Format
CAUTION: You have to read the data in the same order and same
format in which they are stored. For example, since names are written
in UTF using writeUTF, you must read names using readUTF.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 27
public static void main(String[] args) {
try {
try (DataOutputStream output =
new DataOutputStream(new FileOutputStream("test.dat"))) {
output.writeDouble(4.5);
output.writeDouble(43.25);
output.writeDouble(3.2);
}
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 29
Tip
You should always use buffered I/O to
speed up input and output.
For small files, you may not notice
performance improvements.
However, for large files (over 100MB), you
will see substantial improvements using
buffered I/O.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 30
BufferedInputStream/
BufferedOutputStream Using buffers to speed up
I/O
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream
ObjectOutputStream PrintStream
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 32
Case Studies: Copy File
This case study develops a program that copies files. The user needs
to provide a source file and a target file as command-line arguments
using the following command:
The program copies a source file to a target file and displays the
number of bytes in the file. If the source does not exist, tell the user
the file is not found. If the target file already exists, tell the user the
file already exists.
Copy
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 33
public class Copy {
/** Main method
@param args[0] for sourcefile
@param args[1] for target file
*/
public static void main(String[] args) throws IOException {
// Check command-line parameter usage
if (args.length != 2) {
System.out.println(
"Usage: java Copy sourceFile targetfile");
System.exit(1);
}
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 34
// Check if target file exists
File targetFile = new File(args[1]);
if (targetFile.exists()) {
System.out.println("Target file " + args[1]
+ " already exists");
System.exit(3);
}
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 35
try (
// Create an input stream
BufferedInputStream input =
new BufferedInputStream(new FileInputStream(sourceFile));
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream
ObjectOutputStream PrintStream
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 37
ObjectInputStream
ObjectInputStream extends InputStream and
implements ObjectInput and ObjectStreamConstants.
java.io.InputStream ObjectStreamConstants
java.io.DataInput
java.io.ObjectInputStream java.io.ObjectInput
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 38
ObjectOutputStream
ObjectOutputStream extends OutputStream and
implements ObjectOutput and ObjectStreamConstants.
java.io.OutputStream ObjectStreamConstants
java.io.DataOutput
java.io.ObjectOutputStream java.io.ObjectOutput
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 39
Using Object Streams
You may wrap an ObjectInputStream/ObjectOutputStream on any
InputStream/OutputStream using the following constructors:
// Create an ObjectInputStream
public ObjectInputStream(InputStream in)
// Create an ObjectOutputStream
public ObjectOutputStream(OutputStream out)
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 40
import java.io.*;
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 42
The Serializable Interface
Not all objects can be written to an output stream. Objects that can be
written to an object stream is said to be serializable. A serializable
object is an instance of the java.io.Serializable interface. So the class
of a serializable object must implement Serializable.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 43
The Serializable Interface
Many classes in the Java API implement
Serializable.
All the wrapper classes for primitive-type values,
BigInteger, BigDecimal, String, StringBuilder,
StringBuffer, Date, and ArrayList implement
Serializable.
Attempting to store an object that does not support
the Serializable interface would cause a
NotSerializableException.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 44
The transient Keyword
If an object is an instance of Serializable, but it contains
non-serializable instance data fields, can the object be
serialized? The answer is no. To enable the object to be
serialized, you can use the transient keyword to mark these
data fields to tell the JVM to ignore these fields when
writing the object to an object stream.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 45
The transient Keyword
Consider the following class:
public class Foo implements java.io.Serializable {
private int v1;
private static double v2;
private transient A v3 = new A();
}
class A { } // A is not serializable
When an object of the Foo class is serialized, only variable v1 is
serialized. Variable v2 is not serialized because it is a static variable,
and variable v3 is not serialized because it is marked transient. If v3
were not marked transient, a java.io.NotSerializableException would
occur.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 46
Duplicate Objects
When an object is written for the first time, Java
virtual machine assigns a serial number to it. The
serial number and contents of objects are written
to the file.
If the same object is written again, only the serial
number will be written.
When the objects are read back, their references
are the same since only one object is actually
created in the memory.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 47
Serializing Arrays
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 48
import java.io.*;
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 49
try ( // Create an input stream for file array.dat
ObjectInputStream input =
new ObjectInputStream(new FileInputStream("array.dat"));
){
int[] newNumbers = (int[])(input.readObject());
String[] newStrings = (String[])(input.readObject());
// Display arrays
for (int i = 0; i < newNumbers.length; i++)
System.out.print(newNumbers[i] + " ");
System.out.println();
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 50
Random Access Files
All of the streams you have used so far are known as
read-only or write-only streams. The external files of
these streams are sequential files that cannot be updated
without creating a new file. It is often necessary to
modify files or to insert new records into files. Java
provides the RandomAccessFile class to allow a file to be
read from and write to at random locations.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 51
RandomAccessFile
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 52
File Pointer
A random access file consists of a sequence of bytes. There is a
special marker called file pointer that is positioned at one of these
bytes. A read or write operation takes place at the location of the file
pointer. When a file is opened, the file pointer sets at the beginning of
the file. When you read or write data to the file, the file pointer moves
forward to the next data. For example, if you read an int value using
readInt(), the JVM reads four bytes from the file pointer and now the
file pointer is four bytes ahead of the previous location.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 53
RandomAccessFile Methods
Many methods in RandomAccessFile are the same as
those in DataInputStream and DataOutputStream.
For example, readInt(), readLong(),
writeDouble(), readLine(), writeInt(), and
writeLong() can be used in data input stream or data
output stream as well as in RandomAccessFile
streams.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 54
RandomAccessFile Methods
void seek(long pos) throws IOException;
Sets the offset from the beginning of the
RandomAccessFile stream to where the next read
or write occurs.
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 55
RandomAccessFile Methods
long length()throws IOException
Returns the length of the file.
RandomAccessFile raf =
new RandomAccessFile("test.dat",
"r"); // read only
Liang, Introduction to Java Programming, Eleventh Edition, (c) 2017 Pearson Education, Inc. All
rights reserved. 57
public class TestRandomAccessFile {
public static void main(String[] args) throws IOException {
try ( // Create a random access file
RandomAccessFile inout = new RandomAccessFile("inout.dat", "rw");
){
// Clear the file to destroy the old contents if exists
inout.setLength(0);