Chapter 12
File Input and Output
Chapter 12 Objectives
After you have read and studied this chapter, you should be able to
• Include a JFileChooser object in your program to let the user specify a file.
• Write bytes to a file and read them back from the file, using
FileOutputStream and FileInputStream.
• Write values of primitive data types to a file and read them back from the file, using DataOutputStream and
DataInputStream.
Chapter 12 Objectives, cont.
After you have read and studied this chapter, you should be able to
• Write text data to a file and read them back from the file, using
PrintWriter and BufferedReader.
• Write objects to a file and read them back from the file, using
ObjectOutputStream and ObjectInputStream.
12.1 File and JFileChooser Objects
The action of saving, or writing, data to a file is called file output.
The action of reading data from a file is called file input.
12.1 File and JFileChooser Objects
Before we can read data from a file, we must create a File object and associate it to the file from which we wish to read.
We do this by calling a File constructor:
File inFile = newFile(“sample.data”);
12.1 File and JFileChooser Objects
This approach assumes that the file is located in the current directory.
Otherwise, we must specify the path and file name when we call the constructor:
File inFile = new
File(“C:/JavaPrograms”,”xyz.data”);
The formatting of the path name and file name is different for different
operating systems.
Fig. 12.1
Directory structure used for the
examples in this section. We assume the Windows environment.
12.1 File and JFileChooser Objects
We can check if a File object is
associated correctly to an existing file by calling its exists method:
if (inFile.exists()){
//inFile is associated correctly to //an existing file
} else {
//inFile is not associated to any //existing file
}
12.1 File and JFileChooser Objects
When a valid association is established, we say a file is opened.
A file must be opened before we can do any input and output to the file.
12.1 File and JFileChooser Objects
A File object may also be associated to a directory.
File directory =
new File (“C:/JavaPrograms/Ch12”);
String filename[] = directory.list();
for (int i=0; i<filename.length; i++){
System.out.println(filename[i]);
}
12.1 File and JFileChooser Objects
To determine if a File object is
associated to a file or directory, we call its boolean method isFile.
A javax.swing.JFileChooser object allows the user to select a file.
JFileChooser chooser = new JFileChooser();
...
chooser.showOpenDialog(null);
Fig. 12.2
A sample JFileChooser object displayed with the
showOpenDialog method. The
dialog title and the okay button are labeled Open.
12.1 File and JFileChooser Objects
The getSelectedFile method retrieves the desired file.
The getName and
getAbsolutePath methods
retrieve the name and full path of a selected file.
The showSaveDialog method displays a JFileChooser with a Save button.
Fig. 12.3
A sample JFileChooser object displayed with the
showSaveDialog method.
12.1 File and JFileChooser Objects
/*
File: TestJFileChooser.java
*/
import java.io.*;
import javax.swing.*;
class Ch12TestJFileChooser {
public static void main (String[] args) { JFileChooser chooser;
File file, directory;
int status;
chooser = new JFileChooser( );
status = chooser.showOpenDialog(null);
if (status == JFileChooser.APPROVE_OPTION) { file = chooser.getSelectedFile();
directory = chooser.getCurrentDirectory();
12.1 File and JFileChooser Objects
System.out.println("Directory: " +
directory.getName());
System.out.println("File selected to open: "
+
file.getName());
System.out.println("Full path name: " + file.getAbsolutePath());
} else {
JOptionPane.showMessageDialog(null,
"Open File dialog canceled");
}
System.out.println("\n\n");
status = chooser.showSaveDialog(null);
12.1 File and JFileChooser Objects
if (status == JFileChooser.APPROVE_OPTION) { file = chooser.getSelectedFile();
directory = chooser.getCurrentDirectory();
System.out.println("Directory: " +
directory.getName());
System.out.println("File selected for saving data: " +
file.getName());
System.out.println("Full path name: " + file.getAbsolutePath());
} else {
JOptionPane.showMessageDialog(null,
"Save File dialog canceled");
} } }
Fig. 12.4
A sample output from running the Ch12TestJFileChooser program once.
12.1 File and JFileChooser Objects
A file filter may be used to remove unwanted files from the list.
Define a subclass of the
javax.swing.filechooser.FileFil ter class and provide the accept and getDescription methods.
public boolean accept(File file) public String getDescription( )
12.1 File and JFileChooser Objects
The accept method returns true if the parameter file is a file to be included in the list.
The getDescription method returns a text that will be
displayed as one of the entries for the “Files of Type:” drop-down list.
12.1 File and JFileChooser Objects
When the filter class is defined, we can set it to a file chooser to
restrict the listing to the desired directories and files.
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new JavaFilter(());
int status = chooser.showOpenDialog(null);
12.2 Low-Level File I/O
Once a file is opened by
associating a File object to it, we can access the file.
To read data from or write data to a file, we must create one of the
Java stream objects and attach it to the file.
12.2 Low-Level File I/O
A stream is a sequence of data items, usually 8-bit bytes.
Java has two types of streams: an input stream and an output
stream.
An input stream has a source form which the data items come, and an output stream has a destination to which the data items are going.
12.2 Low-Level File I/O
FileOutputStream and
FileInputStream are two stream objects that facilitate file access.
FileOutputStream allows us to output a sequence of bytes;
values of data type byte.
12.2 Low-Level File I/O
We will process the following byte array:
byte[] byteArray = {10, 20, 30, 40, 50, 60, 70, 80};
We create a File object:
File outFile = new File (“sample1.data”);
Associate a new FileOutputStream object to outFile:
FileOutputStream outStream = new FileOutputStream(outFile);
and write the whole byte array at once to the file:
outstream.write(byteArray);
12.2 Low-Level File I/O
After the values are written to the file, we must close the stream:
outStream.close();
If the stream object is not closed, then data may get lost due to data caching.
12.2 Low-Level File I/O
Data is saved in blocks of bytes to reduce the time it takes to save all of our data.
The operation of saving data as a block is called data caching.
To carry out data caching, part of memory is reserved as a data
buffer or cache, which is used as a temporary holding place.
12.2 Low-Level File I/O
Data are first written to a buffer.
When the buffer becomes full, the data in the buffer are actually
written to a file.
If there are any remaining data in the buffer and the file is not
closed, those data will be lost.
12.2 Low-Level File I/O
To read data into a program, we reverse the steps in the output routine.
We use the read method of
FileInputStream to read in an array of bytes.
12.2 Low-Level File I/O
First we create a FileInputStream object:
File inFile = new File(“sample1.data”);
FileInputStream inStream = new FileInputStream(inFile);
Then we must declare and create byteArray:
int filesize = (int) inFile.length();
byte[] byteArray = new byte[filesize];
12.2 Low-Level File I/O
We use the length method of the File class to determine the size of the file.
This allows us to create an array of bytes whose size is the size of the file.
Finally, we read the data into an array of bytes:
inStream.read(byteArray);
12.2 Low-Level File I/O
We can output data other than bytes if we can type cast them into bytes.
To read the data back, we use the read method.
Depending on the data type we
converted the data from, we may need to type cast back into the original data type.
12.3 High-Level File I/O
Using DataOutputStream allows us to output Java primitive data type values.
A DataOutputStream object will convert the primitive data type values into a sequence of bytes.
12.3 High-Level File I/O
The argument to the
DataOutputStream constructor is a FileOutputStream object.
A DataOutputStream object does not get connected to a file directly.
The role of a DataOutputStream object is to provide high-level
access to a file by handling the data type conversions.
Fig. 12.5
A diagram showing how the three objects outFile, outFileStream, and outDataStream are related.
12.3 High-Level File I/O
To read data back from the file, we reverse the operation.
We use three objects: File, FileInputStream, and
DataInputStream.
Data must be read in the order in which it was written; otherwise, the results will be unpredictable.
Fig. 12.6
A diagram showing how the three objects inFile, inFileStream, and inDataStream are related.
Fig. 12.7
The order of write and read
operations must match to read the stored data back correctly.
12.3 High-Level File I/O
FileOutputStream and
DataOutputStream objects
produce a binary file in which the contents are stored in the format (binary format) in which they are stored in the main memory.
12.3 High-Level File I/O
Data may be stored in ASCII format instead of binary format.
With ASCII format, all data are converted to string data.
A file whose contents are stored in ASCII format is called a text file.
12.3 High-Level File I/O
PrintWriter is an object we use to generate a textfile.
PrintWriter supports only two output methods:
• println (for print line)
12.3 High-Level File I/O
An argument to the methods may be any primitive data type.
The methods convert the
parameter to string and output this string value.
The constructor of PrintWriter, like that of DataOutputStream, requires an output stream as its argument.
12.3 High-Level File I/O
To read data from a text file, we use the FileReader and
BufferedReader objects.
• We first associate a BufferedReader object to a file.
• Then we read data, using the readLine method of
BufferedReader.
• Finally, we convert the String to a primitive data type as necessary.
12.3 High-Level File I/O
File inFile = new File(“sample3.data”);
FileReader fileReader = new FileReader(inFile);
BufferedReader bufReader = new BufferedReader(fileReader)
String str = bufReader.readLine();
12.4 Object I/O
We can now store objects just as we can store primitive data
values.
To write objects to a file, we use ObjectOutputStream.
To read objects from a file, we use ObjectInputStream.
12.4 Object I/O
In this example, we will write Person objects to a file.
The first step is to modify the
Person class definition to allow ObjectOutputStream and
ObjectInputStream to perform object I/O.
12.4 Object I/O
We modify the definition by adding the phrase implements
Serializable to it.
import java.io.*;
class Person implements Serializable { //the rest is the same
}
There are no methods for us to define in the implementation class.
12.4 Object I/O
To save objects to a file, we first
create an ObjectOutputStream object:
File outFile = new File(“objects.dat”);
FileOutputStream outFileStream = new FileOutputStream(outFile);
ObjectOutputStream outObjectStream = new ObjectOutputStream(outFileStream);
12.4 Object I/O
To save a Person object, we execute
Person person = new
Person(“Mr. Espresso”, 20, ‘M’);
outObjectStream.writeObject(person);
12.4 Object I/O
Different types of objects may be saved to a single file.
We can also mix objects and
primitive data type values in the same file.
12.4 Object I/O
To read objects from a file, we use FileInputStream and
ObjectInputStream.
We use the method readObject to read an object.
Because we can store any types of objects to a single file, we must
type cast the object read from the file.
12.4 Object I/O
The readObject method can throw a ClassNotFoundException
(wrong type casting) in addition to an IOException.
Either exception may be caught or propagated.
12.4 Object I/O
If a file contains objects from
different classes, they must be read in the correct order and the matching type casting must be applied.