C SC 160 Chapter 12 topic: File Input/Output
major resource: An Introduction to Object-Oriented Programming with
Java, fourth edition, Wu, McGraw Hill, 2006
[ previous
| schedule
| next ]
Overview
- Files used for persistent storage of data and information
- Java recognizes two kinds of file objects: directories, and files
- directory == folder
- files can be classified as either text or binary files
- text file is one whose contents can be viewed by ASCII editor such as Notepad
- binary file is one whose contents cannot be correctly viewed by ASCII editor
- values of primitive type can be stored in either text or binary format
- Java objects can be directly stored if their class implements Serializable
- protocol for reading from a file:
- get the file
- open a reading stream
- invoke read method one or more times
- close the reading stream
- protocol for writing to a file
- get the file
- open a writing stream
- invoke write method one or more times
- close the writing stream
- The file represents a communication endpoint, a data source or sink.
- The stream is a device-independent medium for reading and writing data.
Opening a File
Basic Explanation: Open a file by creating a java.io.File object to represent the open
file. Provide the
file name as a String argument to the File constructor.
Extended Explanation: The procedure for opening a file is covered in
the Basic Explanation. The more interesting part is selecting which file to
open.
- If the file name is known and fixed, it can be specified as a literal String
argument, e.g. File myFile = new File("settings.dat");
- If the file name is not known in advance, then somehow get the file name into a String variable,
e.g. File myFile = new File(fileName);
- specifying where the file is located
- current directory: the directory in use when the JVM is run. In this case the filename
by itself is given, e.g. File myFile = new File("settings.dat");
- absolute pathname: the filename is preceded by the complete directory path from the root
of its storage volume. In Windows, the root is a physical/logical drive letter, e.g. "C:\" or server
name, e.g. "\\Math". Each name in the path leading to the filename is a directory and they are separated by the "/"
or "\" separator. Note: if "\" is used, you have to double it to "\\".
Example: File myFile = new File("C:/pete/csc160/settings.dat");
- relative pathname a directory path is provided which is relative to the current directory.
If it is necessary to go a level up the directory structure, use ".." to represent the
parent directory. Example: if the current directory is C:/pete, then you can open file
C:/pete/csc160/settings.dat using File myFile = new File("csc160/settings.dat");
Example: if the current directory is C:/pete/csc160/spring2004, you can open the same
file using File myFile = new File("../settings.dat");
- getting file name from the user
- user types it as command line argument when the Java program is run. It will be available in
main() through that funny String[] args parameter you always have to provide
but have never used before!
- user types it in via JOptionPane or other textual input technique
- user selects it with a mouse using JFileChooser
Using JFileChooser
- Like JOptionPane, this can be used either with or without a frame.
- Unlike JOptionPane, you create an object and use its methods (rather than using static methods)
- Start by creating a JFileChooser object
- Once the JFileChooser object is created, initiate a dialog with the user
- invoke its showOpenDialog() method to
get a dialog for selecting a file to open.
- invoke its showSaveDialog() method to
get a dialog for selecting a directory and filename for saving.
- both have a parameter where you can supply a frame (or other GUI) object or null for centering
- both return an int status value indicating which button was clicked to end the dialog
- Once the open/save dialog is completed, check its return value (status)
- if JFileChooser.CANCEL_OPTION, the user cancelled the operation so your program should
proceed accordingly
- if JFileChooser.APPROVE_OPTION, the user selected a file
- Assuming the user did not cancel, the file is open
- retrieve the File object representing the selected file using the
chooser's getSelectedFile() method
- You can proceed to use the File object for reading, writing, or other operation
I/O Streams
File writing and reading operations are based on the concept of streams
- A stream is an unstructured sequence of atomic data items, usually bytes
- The program applies structure to the stream
- Analogy: If you transferred into Otterbein, we receive your
transcript as a list of courses you've taken (the stream). We assign Otterbein course equivalents then apply
our degree requirements (structure) to determine what remaining courses you have to take.
- Stream concept comes from Unix
Significance of the stream concept: it is device-independent. A method that works with
a stream does not know what is at the other end of the stream -- it could be a disk file, an Internet
socket, a lab instrument, a remote procedure call...and it doesn't matter!
A stream object is normally connected to a device when the stream is constructed, but the stream
methods are the same regardless of the device type.
Stream contents can be stored in either text or binary format
- text format means that the ASCII/Unicode codes for the values are stored.
- writing the integer
value 23 to a file causes the characters '2' and '3' to be stored (decimal values 50 and 51)
- you can accurately view the contents of such a file using an plain text editor like Notepad
- many data are now stored/transferred using XML, which is a text format
- binary format means "anything but textual", such as storing the actual bits of the values.
- writing the integer
value 23 to a file causes decimal 23 to be stored (bit pattern 10111 left-padded with 0's)
- the contents of such a file look like gibberish when viewed through Notepad. Why?
When you develop software, you can choose to record file data using either text or binary format. What
are the advantages and disadvantages of each?
Writing to a file stream
Java provides a variety of techniques for writing data, each with its own "writer" class.
Here are three:
- Write raw bytes in binary format
- save data into a byte array
- create a FileOutputStream object, giving the File object
as constructor argument
- invoke its write() method with the byte array as argument
- Write primitive types in binary format
- create a FileOutputStream object, giving the File object
as constructor argument
- create a DataOutputStream object, giving the FileOutputStream
object as constructor argument
- to write an int value, invoke its writeInt() method
- to write a double value, invoke its writeDouble()
method
- similar for the other primitive types
- Write primitive types in text format (ASCII)
- create a FileOutputStream object, giving the File object
as constructor argument
- create a PrintWriter object, giving the FileOutputStream
object as constructor argument
- use its print() and println() methods to write a value,
which is converted to String for writing
Notice that for the second and third flavors, we started by creating a FileOutputStream object that contained
the File, then created a specialized stream object that contained the FileOutputStream
object.
FileOutputStream is like a vanilla ice cream cone; you can eat it
plain (raw bytes in binary form), or you can choose add-ins like sprinkles (primitives
in binary form) or butterscotch dip (primitives in text form) to customize it!
Notice also, that these were all used to write primitive data. What about objects?
- objects can be easily written to file if their class implements the Serializable
interface
- the Serializable interface does not have any methods!
- if a class is not serializable, you can create an empty subclass that implements Serializable
and then write objects created from the subclass
- The basic procedure for writing an object is
- create a FileOutputStream object, giving the File object
as constructor argument
- create an ObjectOutputStream object, giving the FileOutputStream
object as constructor argument
- invoke its writeObject() method with the desired object as argument
Reading from a file stream
File reading operations, like writing, are based on the stream concept.
The basic idea for reading is to use the equivalent technique that was used for writing the data!
Java provides a variety of techniques for reading data, each with its own "reader" class.
Here are the three that correspond to the writing techniques described above:
- Read raw bytes in binary format
- Create a byte array to contain the data to be read
- create a FileInputStream object, giving the File object
as constructor argument
- invoke its read() method with the byte array as argument
- Read primitive types in binary format
- create a FileInputStream object, giving the File object
as constructor argument
- create a DataInputStream object, giving the FileInputStream
object as constructor argument
- to read an int value, invoke its readInt() method (no parameters, returns value)
- to read a double value, invoke its readDouble()
method
- similar for the other primitive types
- Read primitive types in text format (ASCII)
- create a FileReader object, giving the File object
as constructor argument
- create a BufferedReader object, giving the FileReader
object as constructor argument
- use its readLine() method to read a String then convert it to the
appropriate primitive type (using e.g. Integer.parseInt(), etc)
- You can alternatively create a Scanner object for the File, and use
its nextInt(), nextDouble(), etc., methods
Objects previously saved using writeObject() can be similarly read back in
- The basic procedure for reading an object is
- create a FileInputStream object giving the File object
as constructor argument
- create an ObjectInputStream object giving the FileInputStream
object as constructor argument
- invoke its readObject() method, which returns an Object that
you then have to typecast to the correct class
Closing a stream
When finished with file operations, please close the reader or writer object you were using by
invoking its close() method.
Exceptions
Many of the methods above are defined with a throws clause to throw a checked exception
(refer to notes on exceptions). A method which invokes such a method must
either handle the exception using try - catch or propagate it by adding the same
throws clause to its own signature. The latter is normally done, but has to be repeated
in the method that invokes it and so forth up the chain all the way to and
including main().
[ C SC 160 | Peter Sanderson | Math Sciences server | Math Sciences home page | Otterbein ]
Last updated:
Peter Sanderson mailto:PSanderson@otterbein.edu