File Handling and DataOutputStream Example
File Handling and DataOutputStream Example
CHAPTER
16
FILE INPUT AND OUTPUT
In this chapter, you will:
♦ Use the File class
♦ Understand data file organization and streams
♦ Use streams
♦ Write to and read from a file
♦ Write formatted file data
♦ Read formatted file data
♦ Use a variable filename
♦ Create random access files
Haven’t I seen you spending a lot of time at the keyboard lately?” asks
Lynn Greenbrier one day at Event Handlers Incorporated.
“I’m afraid so,” you answer. “I’m trying to write a program that displays a
month’s scheduled events, one at a time. Every time I run it, I have to enter
the data for every event—the host’s name, the number of guests, and so on.”
“You’re typing all the data over and over again?” Lynn asks in disbelief. “It’s
time for me to show you how to save data to a file.”
577
16 Chapter A4758 5/3/04 4:52 pm Page 578
For convenience, the data file used in this example is stored on a floppy disk.
However, business files are usually stored on a hard disk, either locally or on
Tip a network server. No matter where a data file is physically located, the process
of saving and retrieving the file is the same.
3. Click the View Event button again to view the data for five additional
events. Click the Close button to exit the program at any time. The program
will also exit automatically when you reach the end of the stored data file.
Although their contents vary, files have many common characteristics—each file occu-
pies a section of disk (or other storage device) space, has a name and a specific time of
[Link] can use Java’s File class to gather file information. The File class does not
provide any opening, processing, or closing capabilities for files. Rather, you use the File
class to obtain information about a file, such as whether it exists or is open, its size, and
its last modification date.
You must include the statement import [Link].* in any program that uses the File
class. The [Link] package contains all the classes you use in file processing. The File class
is a direct descendant of the Object [Link] can create a File object using a constructor
that includes a filename; for example, File someData = new File("[Link]");,
where [Link] is a file on the default disk [Link] can also specify a path for the file, as
in File someData = new File("A:\\Chapter.16\\[Link]");, in which the
argument to the constructor contains a disk drive and path. Table 16-1 lists some useful
File class methods.
Tip
Recall that the backslash (\) is used as part of an escape sequence in Java.
You must type two backslashes to indicate a single backslash to the operat-
Tip ing system. You learned about the escape sequence in Chapter 2.
Next you will write a class that examines a file and prints appropriate messages con-
cerning its status.
16 Chapter A4758 5/3/04 4:52 pm Page 580
Next you will change the program to test for a file that does not exist.
To check for a nonexistent file:
1. Open the [Link] file from the Chapter.16 folder in your text edi-
tor, and then immediately save it as [Link].
2. Change the class name to CheckFile2.
3. Change the filename in the File constructor so that it refers to a nonexistent file:
FileƒmyFileƒ=ƒnewƒFile("[Link]");
4. Save the file, and then compile and run the program. Unless you have a file
named [Link] on your Student Disk, the output looks like Figure 16-3.
16
Figure 16-3 Output of the CheckFile2 program
In the preceding steps, the program found the file named [Link] because the file
was physically located in the current directory from which you were working. You
can check the status of files in other directories by using a File constructor with two
String arguments. The first String represents a path to the filename, and the second
String represents the filename. For example, File someFile = new File("\\
com\\EventHandlers","[Link]"); refers to the [Link] file located in the
EventHandlers folder within the com folder in the root directory.
Next you will create a second data file so that you can compare its size and time stamp
with the [Link] file.
16 Chapter A4758 5/3/04 4:52 pm Page 582
Because you can erase data from files, some programmers prefer the term
persistent storage over permanent storage. In other words, you can remove
Tip data so it is not permanent, but the data remains in the file even when the
computer loses power, so, unlike RAM, the data will persist, or persevere.
Data used by businesses is stored in a data hierarchy, as shown in Figure [Link] small-
est, useful piece of data that is of interest to most people is the character. A character is
any one of the letters, numbers, or other special symbols, such as punctuation marks, you
can read and to which you can assign meaning. Characters are made up of bits (the zeros
and ones that represent computer circuitry), but people who use data are not concerned
with whether the internal representation for an A is 01000001 or 10111110.
Java uses Unicode to represent its characters. You first learned about Unicode
Tip
in Chapter 2.
16
When businesses use data, they group characters into fields. A field is a group of char-
acters that has some meaning. For example, the characters T, o, and m might represent
your first name. Other data fields might represent items such as last name, Social Security
number, zip code, and salary.
16 Chapter A4758 5/3/04 4:52 pm Page 584
Characters: B r o w n
Fields are grouped together to form records. An individual’s first and last names, Social
Security number, zip code, and salary represent that individual’s [Link] program-
ming in Java, you have created many classes, such as an Employee class or a Student class.
You can think of the data typically stored in each of these classes as a [Link] classes
contain individual variables that represent data fields. A business’s data records usually
represent a person, item, sales transaction, or some other concrete object or event.
Records are grouped to create files. Files consist of related records, such as a company’s
personnel file that contains one record for each company employee. Some files have only
a few records; perhaps your professor maintains a file for your class with 25 records—one
record for each student. Other files contain thousands or even millions of records. For
example, a large insurance company maintains a file of policyholders, and a mail-order
catalog company maintains a file of available items.
Before a program can use a data file, the program must open the file. Similarly, when
you finish using a file, the program should close the file. If you fail to close an input file—
that is, a file from which you are reading data, there usually are not any serious conse-
quences; the data still exists in the file. However, if you fail to close an output file—that
is, a file to which you are writing data, the data may become inaccessible. You should
always close every file you open, and you should close the file as soon as you no longer
need [Link] you leave a file open for no reason, you use computer resources and your
computer’s performance suffers. Also, particularly within a network, another program
might be waiting to use the file.
While people view files as a series of records with each record containing data fields, Java
views files as a series of bytes. When you perform an input operation in a program, you
can picture bytes flowing into your program from an input device through a stream,
which functions as a pipeline or [Link] you perform output, some bytes flow out
of your program through another stream to an output device, as shown in Figure 16-6.
A stream is an object, and like all objects, streams have data and methods. The methods
allow you to perform actions such as opening, closing, and flushing (clearing) the stream.
16 Chapter A4758 5/3/04 4:52 pm Page 585
INPUT
PROGRAM
OUTPUT
Most streams flow in only one direction; each stream is either an input or output stream.
You might open several streams at once within your program. For example, three streams
are required by a program that reads a data disk. One input stream checks the data for
invalid values, and then one output stream writes some records to a file of valid records;
another output stream writes other records to a file of invalid records.
Random access files use streams that flow in two directions. You will use a
random access file later in this chapter.
Tip
USING STREAMS
Figure 16-7 shows a partial structure of Java’s Stream classes; it shows that InputStream
and OutputStream are subclasses of the Object class. InputStream and OutputStream
are abstract classes that contain methods for performing input and output. As abstract
classes, these classes contain methods that must be overridden in their child [Link]
capabilities of the most commonly used classes that provide input and output are sum-
marized in Table 16-2.
Table 16-2 Description of selected classes used for input and output
Class Description
InputStream Abstract class containing methods for performing input
OutputStream Abstract class containing methods for performing output
16
FileInputStream Child of InputStream that provides the capability to read from
disk files
FileOutputStream Child of OutputStream that provides the capability to write to
disk files
PrintStream Child of FilterOutputStream, which is a child of OutputStream;
PrintStream handles output to a system’s standard (or default)
output device, usually the monitor
BufferedInputStream Child of FilterInputStream, which is a child of InputStream;
BufferedInputStream handles input from a system’s standard (or
default) input device, usually the keyboard
16 Chapter A4758 5/3/04 4:52 pm Page 586
Object
|
+--InputStream
| |
| +--FileInputStream
| |
| +--FilterInputStream
| |
| +--DataInputStream
| |
| +--BufferedInputStream
|
+--OutputStream
| |
| +--FileOutputStream
| |
| +--FilterOutputStream
| |
| +--DataOutputStream
| |
| +--BufferedOutputStream
| |
| +--PrintStream
|
+--RandomAccessFile
Java’s System class declares a PrintStream object. This object is [Link], which you
have used extensively in this book. Besides [Link], the System class defines an addi-
tional PrintStream object named [Link]. The output from [Link] and
[Link] can go to the same device; in fact, [Link] and [Link] are both
directed to the command line on the [Link] difference is that [Link] usually
is reserved for error messages, and [Link] is reserved for valid [Link] can direct
either [Link] or [Link] to a new location, such as a disk file or printer. For
example, you might want to keep a hard copy log of the error messages generated by a
program, but direct the standard output to a disk file.
Figure 16-7 shows that the InputStream class is parent to FilterInputStream, which is
parent to BufferedInputStream. The object [Link] is a BufferedInputStream object.
The [Link] object captures keyboard input. Recall that you have used this object
with its read() method. A buffer is a small memory location that you use to hold data
temporarily. The BufferedInputStream class allows keyboard data to be held until the
user presses [Enter]. That way, the user can backspace over typed characters to change
the data before the program stores [Link] allows the operating system—instead of your
program—to handle the complicated tasks of deleting characters as the user backspaces,
and then replacing the deleted characters with new ones.
16 Chapter A4758 5/3/04 4:52 pm Page 587
Using a buffer to hold input or output improves program performance. Input and
output operations are relatively slow compared to computer processor speeds.
Tip Holding input or output until there is a “batch” makes programs run faster.
You can create your own InputStream and OutputStream objects and assign to them
[Link] and [Link], respectively. Then you can use the InputStream’s read()
method to read in one character at a time from the location you choose. The read()
method returns an integer that represents the Unicode value of the typed character; it
returns a value of -1 when it encounters an end-of-file condition, known as EOF.
You can also identify EOF by throwing an EOFException. You will use this
technique later in this chapter.
Tip
Next you will create InputStream and OutputStream objects so you can read from the
keyboard and write to the screen. Of course, you have already written many programs
that read from the keyboard and write to the screen without using these objects. By
using them here with the default input/output devices, you can easily modify the
InputStream and OutputStream objects at a later time; then you can use whatever input
and output devices you choose.
To create a program that reads from the keyboard and writes to the screen:
1. Open a new file in your text editor, and then type the following first few
lines of a program that will allow a user to input data from the keyboard and
then will echo that data to the screen. The class name is
ReadKBWriteScreen:
importƒ[Link].*;
publicƒclassƒReadKBWriteScreen
{
2. Add the following header and opening curly brace for the main() method.
The main() method throws an IOException because you will perform input
and output operations. 16
publicƒstaticƒvoidƒmain(String[]ƒargs)ƒthrowsƒIOException
{
3. Enter the following code to declare InputStream and OutputStream objects,
as well as an integer to hold each character the user types:
InputStreamƒistream;
OutputStreamƒostream;
intƒc;
4. Enter the following code to assign the [Link] object to istream, and the
[Link] object to ostream. Then add a prompt telling the user to type
some characters.
16 Chapter A4758 5/3/04 4:52 pm Page 588
istreamƒ=ƒ[Link];
ostreamƒ=ƒ[Link];
[Link]("Typeƒsomeƒcharactersƒ");
5. Use the following try block to read from the file. If an IOException occurs,
you can print an appropriate message. Within the try block, execute a loop
that reads from the keyboard until the end-of-file condition occurs (when the
read() method returns -1). While there is not an end-of-file condition, send
the character to the ostream object.
Tip
try
{
ƒƒƒƒƒƒwhile((cƒ=ƒ[Link]())ƒ!=ƒ-1)
ƒƒƒƒƒƒƒƒƒƒƒƒƒ[Link](c);
}
6. Use the following catch block to handle any IOException:
catch(IOExceptionƒe)
{
ƒƒƒƒƒƒƒ[Link]("Error:ƒ"ƒ+ƒ[Link]());
}
7. Regardless of whether an IOException occurs, you want to close the streams.
Use the following finally block to ensure that the streams are closed:
finally
{
ƒƒƒƒƒƒƒ[Link]();
ƒƒƒƒƒƒƒ[Link]();
}
8. Add a closing curly brace for the main() method and another for the class.
9. Save the file as [Link] in the Chapter.16 folder on your
Student Disk, and then compile and run the program. At the command line,
type any series of characters and then press [Enter]. As you type characters,
the buffer holds them until you press [Enter], at which time the stored char-
acters echo to the screen. Do not try to end the program yet.
The while loop in the ReadKBWriteScreen program continues until the read()
method returns -1. However, you cannot end the program by typing -[Link] a minus
sign (-) and a one (1) causes two additional characters to be sent to the buffer, and nei-
ther of those characters represents -1. Instead, you must press [Ctrl] + Z, which forces
the read() method to return -1, and which the operating system recognizes as the end
of the file. Next you will end the ReadKBWriteScreen program.
16 Chapter A4758 5/3/04 4:52 pm Page 589
2. Execute the program again. This time, type a line of characters, press [Enter],
and observe the echoed output. Then type another line, and press [Enter].
You can type as many lines as you want. Press [Ctrl]+Z, and then press
[Enter]. The program will continue to echo your lines to the screen until
you end the program.
Do not press [Ctrl]+C to end the program. Doing so breaks out of the pro-
gram before its completion and does not properly close the files.
Tip
■ You can create a File object passing the filename to the File constructor.
Then you can pass the File object to the constructor of the
FileOutputStream class.
The second method has some benefits—if you create a File object, you can use the File class
methods such as exists() and lastModified() to retrieve file information. In the next set of
steps you will use a FileOutputStream to write keyboard-entered data to a file you create.
Because applets are designed for distribution over the Internet, you are not
allowed to use an applet to write to files on a client’s workstation. Applets
Tip that write to a client’s file could destroy a client’s existing data.
The meaning of the acronym UTF is disputed by various sources. The most
popular interpretations include Unicode Transformation Format, Unicode
Tip Transfer Format, and Unicode Text Format.
importƒ[Link].*;
importƒ[Link].*;
importƒ[Link].*;
importƒ[Link].*;
publicƒclassƒCreateEventFileƒextendsƒJFrame
ƒƒimplementsƒActionListener
{
2. Enter the following code to create a JLabel for the company name and a
Font object to use with the company name:
privateƒJLabelƒcompanyNameƒ=ƒƒ
ƒƒƒnewƒJLabel("EventƒHandlersƒIncorporated");
FontƒbigFontƒ=ƒnewƒFont("Helvetica",ƒ[Link],ƒ24);
3. Enter the following code to create a prompt that tells the user to enter data,
and JTextFields for the host, date, and guests. Because a host’s name is usually
several characters long, the field for the host’s name should be wider than the
fields for the date and number of guests.
privateƒJLabelƒpromptƒ=ƒ
ƒƒƒnewƒJLabel("Enterƒthisƒmonth'sƒevents");
privateƒJTextFieldƒhostƒ=ƒnewƒJTextField(10);
privateƒJTextFieldƒdateƒ=ƒnewƒJTextField(4);
privateƒJTextFieldƒguestsƒ=ƒnewƒJTextField(4);
4. Enter the following code to create a JLabel for each of the JTextFields.
Include a JButton object that the user can click when a data record is com-
pleted and ready to be written to the data file. Then add a Container to hold
the JFrame components.
privateƒJLabelƒhLabelƒ=ƒnewƒJLabel("Host");
privateƒJLabelƒdLabelƒ=ƒnewƒJLabel("Date");
privateƒJLabelƒgLabelƒ=ƒnewƒJLabel("Guests");
privateƒJButtonƒenterDataButtonƒ=ƒƒƒ
ƒƒƒnewƒJButton("Enterƒdata");
privateƒContainerƒconƒ=ƒgetContentPane();
5. When you write the user’s data to an output file, you will use the 16
DataOutputStream class, so create a DataOutputStream object as follows:
DataOutputStreamƒostream;
6. Save the work you have done so far as [Link] in the
Chapter.16 folder on your Student Disk.
Next you will add the CreateEventFile’s constructor to the class. The constructor calls
its parent’s constructor, which is the JFrame class constructor, and passes it a title to use
for the [Link] constructor also attempts to open an [Link] file for output. If the
open fails, the constructor’s catch block handles the Exception; otherwise you add all
the JTextFields, JLabel, and JButton Components to the JFrame.
16 Chapter A4758 5/3/04 4:52 pm Page 594
3. After the file is open, use the following code to set the JFrame’s size, choose a
layout manager, and add all the necessary Components to the JFrame:
setSize(320,200);
[Link](newƒFlowLayout());
[Link](bigFont);
[Link](companyName);
[Link](prompt);
[Link](hLabel);
[Link](host);
[Link](dLabel);
[Link](date);
[Link](gLabel);
[Link](guests);
[Link](enterDataButton);
4. To finish the JFrame constructor, enter the following code to register the
JFrame as a listener for the JButton, make the JFrame visible, and set the
default close operation for the JFrame. Finally, add a closing curly brace for
the constructor.
ƒƒƒ[Link](this);
ƒƒƒsetVisible(true);
ƒƒƒsetDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
16 Chapter A4758 5/3/04 4:52 pm Page 595
5. Save the file. Don’t compile the file yet; you will add more code in the next
set of steps.
When the users see the JFrame, they can enter data in each of the available JTextFields.
When users complete a record for a single event, they click the JButton, which causes
the actionPerformed() method to [Link] method must retrieve the text from each
of the JTextFields and write it to a data file in the correct [Link] will write a use-
able actionPerformed() method now.
To add the actionPerformed() method to the CreateEventFile program:
1. At the end of the existing code within the [Link] file, press
[Enter] to start a new line below the constructor method, and then type the
following header for the actionPerformed() method. Within the method, cre-
ate an integer variable that will hold the number of guests at an event.
publicƒvoidƒactionPerformed(ActionEventƒe1)
{
ƒƒintƒnumGuests;
2. Use a try block to hold the data retrieval and the subsequent file-writing
actions so that you can handle any I/O errors that [Link] will use the
parseInt() method to convert the JTextField guest number to a usable integer, but
you will accept the host and date fields as simple [Link] can use the appropri-
ate DataOutputStream methods to write formatted data to the output file.
You first learned about parseInt() and the Integer class in Chapter 7.
Tip
try
{
ƒƒƒnumGuestsƒ=ƒ[Link]([Link]());
ƒƒƒ[Link]([Link]());
ƒƒƒ[Link]([Link]());
ƒƒƒ[Link](numGuests);
3. Continue the try block by removing the data from each JTextField after it is
16
written to the file. That way, each JTextField will be clear and ready to
receive data for the next record. Notice that to clear the fields, you use a pair
of quotes with no space between them. Then end the try block.
ƒ[Link]("");
ƒ[Link]("");
ƒ[Link]("");
}
4. There are two types of Exceptions that you might want to deal with in this
application. Because the host name and date fields are text, the user can enter
any type of data. However, the guest field must be an integer. When you use
the parseInt() method with data that cannot be converted to an integer (such
16 Chapter A4758 5/3/04 4:52 pm Page 596
3. Type sample data into the JTextFields in the JFrame. Specifically, type Sagami
as the event host, on the 3(rd), with 150 guests. After entering the data into the
three data fields, click the Enter data [Link] data is sent to the file, and
the fields are cleared. Now you can enter a second record (make up your own
record information), and then click the Enter data button again. Repeat this
process until you have entered five data [Link] entering at least one
record, type non-numeric data in the guest field. Notice the error message that
displays on the standard error device at the command line.
4. Click the Close button in the CreateEventFile JFrame to close it.
5. Examine your Student Disk using any file-management program or the DOS
command-line directory command, dir. Confirm that your program created
the [Link] data file in the Chapter.16 folder on your Student [Link]
will write a program to read the file in the next series of steps.
Next you will create a JFrame in which employees of Event Handlers Incorporated can
view each individual record stored in the [Link] [Link] user interface will look like
the interface used in the CreateEventFile JFrame, but the user will not enter data within
16 Chapter A4758 5/3/04 4:52 pm Page 598
this JFrame. Instead, the user will click a JButton to see each succeeding record in the
[Link] file.
To create a JFrame for viewing file data:
1. Open a new file in your text editor, and then type the following first few
lines of the ReadEventFile class:
importƒ[Link].*;
importƒ[Link].*;
importƒ[Link].*;
importƒ[Link].*;
publicƒclassƒReadEventFileƒextendsƒJFrameƒ
ƒƒƒimplementsƒActionListenerƒ
{
2. Enter the following code to declare all of the JLabels, JTextFields, and
associated values that will appear in the JFrame. The text of the prompt and
JButton have changed, but these statements basically echo the statements in
the [Link] file.
privateƒJLabelƒcompanyNameƒ=ƒ
ƒƒƒnewƒJLabel("EventƒHandlersƒIncorporated");
FontƒbigFontƒ=ƒnewƒFont("Helvetica",ƒ[Link],ƒ24);
privateƒJLabelƒpromptƒ=ƒƒnewƒ
ƒƒƒJLabel("Viewƒthisƒmonth'sƒevents");
privateƒJTextFieldƒhostƒ=ƒnewƒJTextField(10);
privateƒJTextFieldƒdateƒ=ƒnewƒJTextField(4);
privateƒJTextFieldƒguestsƒ=ƒnewƒJTextField(4);
privateƒJButtonƒviewEventButtonƒ=ƒnewƒ
ƒƒƒJButton("ViewƒEvent");
privateƒJLabelƒhLabelƒ=ƒnewƒJLabel("Host");
privateƒJLabelƒdLabelƒ=ƒnewƒJLabel("Date");
privateƒJLabelƒgLabelƒ=ƒnewƒJLabel("Guests");
privateƒContainerƒconƒ=ƒgetContentPane();
3. Enter the following code to declare a DataInputStream object. Then write
the ReadEventFile constructor method that uses a try...catch block to
open a file. Notice that you can chain the DataInputStream object and a
FileInputStream object using the same technique you used for output. (Note:
If you have stored your [Link] file in a location other than A:\Chapter.16,
then change the location in the FileInputStream constructor in your own
program.)
DataInputStreamƒistream;
publicƒReadEventFile()
{
ƒƒƒsuper("ReadƒEventƒFile");
ƒƒƒtry
ƒƒƒ{
16 Chapter A4758 5/3/04 4:52 pm Page 599
ƒƒƒƒƒƒƒƒƒistreamƒ=ƒnewƒDataInputStream
ƒƒƒƒƒƒƒƒƒƒƒ(newƒFileInputStream
ƒƒƒƒƒƒƒƒƒƒƒ("A:\\Chapter.16\\[Link]"));
ƒƒƒ}
ƒƒƒcatch(IOExceptionƒe)
ƒƒƒ{
ƒƒƒƒƒƒƒƒƒƒ[Link]("Fileƒnotƒopened");
ƒƒƒƒƒƒƒƒƒƒ[Link](1);
ƒƒƒ}
4. After successfully opening the file, set the JFrame size, layout manager, and
Font for the JFrame as follows:
setSize(325,200);
[Link](newƒFlowLayout());
[Link](bigFont);
5. Add the JFrame’s Components as follows:
[Link](companyName);
[Link](prompt);
[Link](hLabel);
[Link](host);
[Link](dLabel);
[Link](date);
[Link](gLabel);
[Link](guests);
[Link](viewEventButton);
6. Enter the following code to ensure that the JFrame listens for JButton mes-
sages, to make the JFrame visible, and to set the default close operation:
[Link](this);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
7. Add the closing curly brace for the ReadEventFile constructor.
8. Type the beginning of the following actionPerformed() method. This method
declares variables for the file field data, and then uses a try block to call the 16
appropriate read() method for each field. Each data field then appears in the
correct JTextField.
publicƒvoidƒactionPerformed(ActionEventƒe1)
{
StringƒtheHost,ƒtheDate;
intƒnumGuests;
try
{
ƒƒƒƒtheHostƒ=ƒ[Link]();
ƒƒƒƒtheDateƒ=ƒ[Link]();
ƒƒƒƒnumGuestsƒ=ƒ[Link]();
16 Chapter A4758 5/3/04 4:52 pm Page 600
ƒƒƒƒ[Link](theHost);
ƒƒƒƒ[Link](theDate);
ƒƒƒƒ[Link]([Link](numGuests));
}
9. Code the following two catch blocks for the try block that reads the data
fields. The first catch block catches the EOFException and calls a closeFile()
method. The second catch block catches IOExceptions and exits the pro-
gram if there is a problem with the file. Notice that the Exceptions have
unique names (e2 and e3) because you cannot declare two data items with
the same name within the same method.
catch(EOFExceptionƒe2)
{
ƒƒƒcloseFile();
}
catch(IOExceptionƒe3)
{
ƒƒƒ[Link]("Errorƒreadingƒfile");
ƒƒƒ[Link](1);
}
10. Add the closing curly brace for the actionPerformed() method.
11. Write the following closeFile() method that closes the DataInputStream
object and exits the program:
publicƒvoidƒcloseFile()
{
ƒƒƒtry
ƒƒƒ{
ƒƒƒƒƒƒƒƒƒƒ[Link]();
ƒƒƒƒƒƒƒƒƒƒ[Link](0);
ƒƒƒ}
ƒƒƒcatch(IOExceptionƒe)
ƒƒƒ{
ƒƒƒƒƒƒƒƒƒƒ[Link]("Errorƒclosingƒfile");
ƒƒƒƒƒƒƒƒƒƒ[Link](1);
ƒƒƒ}
}
12. Add the closing curly brace for the class.
13. Save the file as [Link] in the Chapter.16 folder on your
Student Disk, and then compile the program using the javac command.
Next you will write a short host program that creates a ReadEventFile JFrame so Event
Handlers employees can examine the existing file of scheduled events.
16 Chapter A4758 5/3/04 4:52 pm Page 601
2. Change the ReadEventFile constructor to the new class name and add an
argument that is a String. The value for this argument will originate from the
first element in the String array (String[]ƒargs) that you have included in
every main() method you have written.
publicƒReadNamedFile(StringƒfileName)
3. Within the try block of the ReadNamedFile constructor, remove the refer-
ence to the filename [Link], and replace it with the variable filename that
represents the String you will use when you call this constructor. In other
words, change the istream assignment to the following:
istreamƒ=ƒnewƒDataInputStream
ƒƒƒƒ(newƒFileInputStream(fileName));
4. Save the file, and then compile the class.
5. Open a new file in your text editor and type the following program that creates
an instance of the ReadNamedFile class. As the argument to the ReadNamedFile
constructor, use the first (and only) String in the array of String arguments that
you will pass to the main() method from the command line.
importƒ[Link].*;
publicƒclassƒEventFile3
{
ƒƒƒpublicƒstaticƒvoidƒmain(String[]ƒargs)
ƒƒƒ{
ƒƒƒƒƒƒƒƒƒƒReadNamedFileƒrefƒ=ƒnewƒReadNamedFile(args[0]);
ƒƒƒ}
}
6. Save the file as [Link] in the Chapter.16 folder on your Student
Disk, and compile the program.
7. You will test the program using the existing file [Link]. To execute the
program, at the command line type javaƒEventFile3ƒ[Link]. The
program executes, correctly showing you the events in the file as before. One
at a time, view each of the records in the file just like you did in the last set
of steps.
8. Attempt to execute the program using a nonexisting filename, for example
javaƒEventFile3ƒ[Link] should see the message “File
not opened”.
in the original data-entry order. Businesses store data in sequential order when they use
the records for batch processing, or processing that involves performing the same tasks
with many records, one after the other. For example, when a company produces pay-
checks, the records for the pay period are gathered in a batch and the checks are calcu-
lated and printed in sequence.
For many applications, sequential access is [Link] applications, known as real-
time applications, require that a record be accessed immediately while a client is wait-
ing. For example, if a customer telephones a department store with a question about a
monthly bill, the customer service representative does not need to access every customer
account in sequence. With tens of thousands of account records to read, it would take
too long to access the customer’s record. Instead, customer service representatives require
random access files, files in which records can be located in any order. Because they
enable you to locate a particular record directly (without reading all of the preceding
records), random access files are also called direct access files. You can use Java’s
RandomAccessFile class to create your own random access files.
The RandomAccessFile class contains the same read(), write(), and close() methods as
InputStream and OutputStream, but it also contains a seek() method that lets you select a
beginning position within a file before you read or write data. For example, if you declare
a RandomAccessFile object named myFile, then the statement [Link](200);
selects the 200th position within the file. The 200th position represents the 201st byte
because, as with Java arrays, the numbering of file positions begins at [Link] next read()
or write() method will operate from the newly selected starting point.
When you store records in a file, it is often more useful to be able to access the 200th
record, rather than the 201st byte. In this case, you multiply each record’s size by the posi-
tion you want to access. For example, if you store records that are 50 bytes long, you
can access the nth record using the statement [Link]((n-1)ƒ*ƒ50);.
When you declare a RandomAccessFile object, you include a filename as you do
with other file [Link] also include r or rw within double quotation marks as a
second argument to indicate that the file is open for reading only (“r”), or for both
reading and writing (“rw”). For example, RandomAccessFileƒmyFileƒ=ƒnew
RandomAccessFile("C:\\Temp\\[Link]","rw"); opens the 16
[Link] file so that either the read() or write() method can be used on the file.
This feature is particularly useful in random access processing. Consider a business
with 20,000 customer accounts. When the customer who has the 14,607 th record in
the file acquires a new telephone number, it is convenient to directly access the
14,607th record, the read() method confirms it represents the correct customer, and
then the write() method writes the new telephone number to the file in the loca-
tion the old telephone number was stored [Link] will demonstrate the seek()
method in the next set of steps.
16 Chapter A4758 5/3/04 4:52 pm Page 604
7. Before you run the file, create a [Link] file by running the ReadKBWriteFile
program you created earlier in this chapter. At the command line, type
javaƒReadKBWriteFile, and then press [Enter].
8. At the prompt, type This is my random access file. Press [Enter], press
[Ctrl]+Z, and then press [Enter] to end the program. (The y in my is the
10th character you type.)
9. At the command line, run the AccessRandomly program by typing
javaƒAccessRandomly. The output is the tenth character in the file, as
shown in Figure 16-12.
In the AccessRandomly program, only one read() command was issued, yet the program
accessed a byte nine positions into the [Link] you access a file randomly, you do not
read all the data that precedes the data you are seeking. Accessing data randomly is one
of the major features that makes large data systems maintainable.
CHAPTER SUMMARY
❒ Files are objects that you store on permanent storage devices, such as floppy disks, 16
CD-ROMs, or external [Link] can use the File class to gather file information.
❒ Data used by businesses generally is stored in a data hierarchy that includes files,
records, fields, and characters.
❒ Java views a file as a series of bytes, and a stream as an object through which input
and output data (in the form of bytes) flow. InputStream and OutputStream are
abstract subclasses of Object that contain methods for performing input and output.
FileInputStream and FileOutputStream provide the capability to read from and write
to [Link] can use the InputStream read()method to read in one character at a time.
❒ You can use the DataInputStream and DataOutputStream classes to accomplish for-
matted input and output. The DataOutput interface includes methods such as
16 Chapter A4758 5/3/04 4:52 pm Page 606
REVIEW QUESTIONS
1. Files always .
a. hold software instructions
b. occupy a section of storage space
c. remain open during the execution of a program
d. all of the above
2. The File class enables you to .
a. open a file
b. close a file
c. determine a file’s size
d. all of the above
3. The package contains all the classes you use in file processing.
a. [Link]
b. [Link]
c. [Link]
d. [Link]
4. The statement FileƒaFileƒ=ƒnewƒFile("myFile"); creates a file
.
a. on the disk in drive A
b. on the hard drive (drive C)
c. in the Temp folder on the hard drive (drive C)
d. on the default disk drive
16 Chapter A4758 5/3/04 4:52 pm Page 607
Exercises 609
EXERCISES
1. Create a file using any word-processing program or text editor. Write a program
that displays the file’s name, parent, size, and time of last modification. Save the
program as [Link] in the Chapter.16 folder on your Student Disk. 16
2. Create two files using any word-processing program or text editor. Write a pro-
gram that determines whether the two files are located in the same folder. Save
the program as [Link] in the Chapter.16 folder on your Student Disk.
3. Write a program that determines which, if any, of the following files are stored in
the Chapter.16 folder of your Student Disk: [Link], [Link],
[Link], and [Link]. Save the program as
[Link] in the Chapter.16 folder on your Student Disk.
4. a. Create a JFrame that allows the user to enter a series of friends’ names and
phone numbers and creates a file from the entered data. Save the JFrame as
[Link] in the Chapter.16 folder on your Student Disk. To use
16 Chapter A4758 5/3/04 4:52 pm Page 610
When the user enters an item number, check the number to make sure that it
is valid. If it is valid, write a record that includes item number, quantity, price
each, and total price. Save the program as [Link] in the
Chapter.16 folder on your Student Disk.
b. Write a program that reads the data file created by the MailOrderWrite2 pro-
gram and displays one record at a time on the screen. Save the program as
[Link] in the Chapter.16 folder on your Student Disk.
7. a. Write a program that allows a user to enter an integer representing a file posi-
tion. Access the requested position within a file and display the character there.
Save the program as [Link] in the Chapter.16 folder on your
Student Disk.
b. Modify the program created by the SeekPosition program so that you display
the next five characters after the requested position. Save the program as
[Link] in the Chapter.16 folder on your Student Disk.
8. a. Write a program that creates a JFrame with text fields for order processing for
a tee-shirt manufacturer. Include JTextFields for size, color, and slogan. Write
each complete record to a file. Save the JFrame as [Link] in the
Chapter.16 folder on your Student Disk. Write a program named
[Link] that displays the JFrame.
16 Chapter A4758 5/3/04 4:52 pm Page 611
b. Write a program that reads the data file created by the TeeShirtWrite program
and displays one record at a time in a JFrame on the screen. Save the program
as [Link] in the Chapter.16 folder on your Student Disk. Write a
program named [Link] that displays the JFrame.
9. Write a program that allows the user to type any number of characters into a file.
Then display the file contents backward. Save the program as
[Link] in the Chapter.16 folder on your Student Disk.
10. a. Create a JFrame that allows you to enter student data—ID number, last name,
and first name. Include two buttons and instruct the user to click “Grad” or
“Undergrad” after entering the data for each student. Depending on the user’s
choice, write the data to either a file containing graduate students or a separate
file containing undergraduate students. Name the JFrame
[Link] and create a program named
[Link] that instantiates a JFrame object. Save both files
in the Chapter.16 folder of your Student Disk.
b. Create a JFrame named [Link] that, in turn, accesses all the
records in the graduate and the undergraduate files created in the
GradAndUndergrad program. Write a program named [Link]
that instantiates a JFrame object. Save both files in the Chapter.16 folder of
your Student Disk.
11. Each of the following files in the Chapter.16 folder on your Student Disk has
syntax and/or logical errors. In each case, determine the problem and fix the pro-
gram. Notice that [Link] and [Link] have companion
files that are part of each exercise. After you correct the errors, save each file using
the same filename preceded with Fix. For example, [Link] will
become [Link].
a. [Link]
b. [Link]
c. [Link]
d. [Link]
16
CASE PROJECT
Create a data-entry and retrieval system for Mowers Inc., a lawn-mowing service. Use a
Case
JFrame to enter data for the customer’s name and lawn size in square feet. An output file
Project
holds the customer name, lawn size, and fee per mowing—$50 for lawns under 1,000
square feet and $75 for lawns 1,000 square feet or more. Name the JFrame
[Link] and save it in the Chapter.16 folder of your Student Disk. Name the
client program that creates an instance of the JFrame [Link]. Retrieve
the created records with a JFrame named [Link] and a client program
named [Link].
16 Chapter A4758 5/3/04 4:52 pm Page 612
Implementing a random access file in large data systems offers significant benefits, mainly by optimizing both data retrieval and maintenance operations. A crucial benefit is the ability to access and manipulate data without reading through every preceding byte, which is intrinsic to sequential file access . Random access files allow records to be accessed directly without regard to their physical location in the file, enhancing performance particularly in large datasets where only specific record updates are required. This streamlines operations such as database index updates, real-time data manipulation, and more efficient insertion/deletion operations within the file . Furthermore, this capability reduces computational overhead and latency in large systems, often resulting in a more responsive application. Java's RandomAccessFile class supports this functionality by providing methods like seek(), which locates any part of the file efficiently before data interaction . Thus, random access files are pivotal in systems requiring quick and efficient data handling beyond traditional sequential methods.
The usage of DataInputStream and DataOutputStream classes allows Java applications to handle formatted data more effectively by providing methods that read and write data in the correct format for the data types. These classes enable the reading and writing of different data types such as integers, doubles, and strings using methods like readInt(), readDouble(), writeInt(), and writeUTF(). This approach ensures data integrity and consistency when performing formatted I/O operations. DataOutputStream writes data in binary format, which is more compact and efficient for storage, albeit not human-readable in text editors . On the other hand, DataInputStream can read this binary formatted data accurately, ensuring seamless data retrieval necessary for processing complex data operations . Thus, these classes are crucial for applications needing structured data management or when reading and writing non-character data formats efficiently.
A major challenge with using the FileOutputStream class is the risk of unintentionally overwriting existing files. When a FileOutputStream object is instantiated using a file name, it opens the file in write mode by default, which overwrites any existing content unless the FileOutputStream append mode is specifically enabled . This default behavior can lead to data loss if precautions are not taken, such as checking whether a file already exists before writing to it or using the appropriate constructor to append new data. Another challenge is related to exception handling; improper management of file closure or erroneous handling of IOExceptions can lead to file corruption or resource leaks, making it vital to use try-with-resources or ensure file streams are closed in finally blocks . Such challenges underline the importance of careful implementation and robust error handling when dealing with file I/O operations in Java.
Using objects like File, FileOutputStream, and InputStream in Java offers several benefits. By using the File class, you can leverage methods such as exists() and lastModified() to retrieve file information. This allows for more robust file manipulation and status checking . The FileOutputStream and InputStream classes facilitate reading from and writing to files by directing input and output data streams to and from file objects, which allows for a consistent method of handling both types of operations in Java . This modular approach to file handling makes the code more versatile, maintainable and easier to understand, as changing the source or destination of data only requires modifying the stream object's assignment rather than the entire program logic . Moreover, these classes enable efficient resource management with exceptions by offering mechanisms to handle errors such as EOFException gracefully, preventing abrupt program termination . Overall, these classes promote effective file I/O management through robust error handling, resource management, and flexible data stream redirection.
In a Java program with a graphical user interface, the actionPerformed() method is essential for facilitating user interactions that result in file operations. When a user performs an action, such as clicking a button, the actionPerformed() method is triggered and executes defined operations such as retrieving data from input fields and writing it to files using methods like DataOutputStream . This method acts as the event handler that translates UI interactions into backend execution, managing tasks like data validation, transforming user inputs into compatible data formats for storage, and triggering processes that update or read from files . In applications like file viewers or editors, actionPerformed() may also update UI components after reading data from a file, ensuring that the visual representation matches the current data state. This integration of UI and file handling enhances user experience by making data processing seamless and interactive, centralizing functionality and improving responsiveness.
Exceptions play a critical role in managing file I/O operations in Java by providing mechanisms to handle errors gracefully, ensuring application stability even when encountering issues such as an unexpected end of file. The EOFException is a specific type of exception that signifies the end of file condition has been reached during a read operation . This exception is particularly useful because it allows the program to anticipate and handle reaching the file's end without further read attempts causing runtime errors. By using try-catch blocks around I/O operations, developers can proactively manage these exceptions, allowing the program to execute alternative actions such as closing files or prompting the user, thereby avoiding a hard crash . This structured error management is integral to maintaining robust file reading processes, ensuring that applications can recover or proceed gracefully when I/O operations don't go as expected, thereby enhancing application reliability and user experience.
Using formatted input and output through DataOutputStream and DataInputStream in Java is particularly advantageous when the application requires reading or writing data types in their native formats efficiently, such as in data serialization or processing binary data files. These scenarios include applications involving data storage where complex data types need to be read and written accurately without conversion errors typical with character-based streams (for instance, database systems or networked applications exchanging binary data). The principal benefits include increased data accuracy, improved storage efficiency, and faster processing speeds since data is stored and retrieved in native binary formats rather than as text . This method provides a structured and more reliable approach to data handling, reducing errors that could occur during data type conversion and preserving the integrity and precision of numerical data like floats or doubles.
Using file streams for client data storage offers a significant advantage over applets, particularly in how and where data is saved. File streams like FileOutputStream and InputStream allow programs to directly read from and write to files stored on the client's system, providing more straightforward and efficient access to data storage and retrieval . This can be particularly useful for creating and maintaining persistent data records. In contrast, applets are restricted from writing to the client’s file system for security reasons. This restriction prevents potential security threats like accidental or malicious overwriting of critical data on client machines . By design, applets offer a secure way to execute on the client's machine without compromising system integrity, although at the cost of reduced data storage capability. Thus, while applets ensure security, file streams provide more flexibility and direct interaction with the file system, making them more suitable for applications where brisk and seamless data handling is required.
Chaining in Java involves linking multiple InputStream or OutputStream objects together to enhance data processing, and this technique is particularly effective when dealing with formatted data using DataInputStream and DataOutputStream. By chaining a DataOutputStream to a FileOutputStream, you can write formatted binary data to a file seamlessly . This allows the Java application to handle complex I/O processes by attaching stream filters (like buffering or compression) without rewriting the core logic. Chaining boosts functionality by enabling a modular approach where different stream concerns, such as formatting or buffering, are handled separately yet integrated into a unified process flow . Thus, chaining makes input and output processes more flexible and extendable, allowing for feature adjustments with minimal disruptions to existing implementations, which is essential for sophisticated and evolving Java applications needing efficient data management.
The method close() in file handling operations is crucial because it ensures that all buffered data is properly flushed to the output file, resources such as file descriptors are released, and the stream is stretched to avoid memory leaks . Neglecting to close file streams can result in multiple issues: resources might remain allocated and eventually exhaust system limits, potentially causing an application to crash or run out of available file handles when attempting to open new files . Additionally, unsaved data might be present in the buffer, leading to data corruption or loss if the application exits before it’s written to disk. The failure to close can also cause synchronization issues in applications that require file locks, potentially leading to data inconsistencies when files are accessed concurrently. Therefore, correctly implementing close() is a fundamental practice for maintaining system integrity and ensuring data is consistently and reliably handled.