- •CONTENTS
- •1.1 Introduction
- •1.2 What Is a Computer?
- •1.3 Programs
- •1.4 Operating Systems
- •1.5 Java, World Wide Web, and Beyond
- •1.6 The Java Language Specification, API, JDK, and IDE
- •1.7 A Simple Java Program
- •1.8 Creating, Compiling, and Executing a Java Program
- •1.9 (GUI) Displaying Text in a Message Dialog Box
- •2.1 Introduction
- •2.2 Writing Simple Programs
- •2.3 Reading Input from the Console
- •2.4 Identifiers
- •2.5 Variables
- •2.7 Named Constants
- •2.8 Numeric Data Types and Operations
- •2.9 Problem: Displaying the Current Time
- •2.10 Shorthand Operators
- •2.11 Numeric Type Conversions
- •2.12 Problem: Computing Loan Payments
- •2.13 Character Data Type and Operations
- •2.14 Problem: Counting Monetary Units
- •2.15 The String Type
- •2.16 Programming Style and Documentation
- •2.17 Programming Errors
- •2.18 (GUI) Getting Input from Input Dialogs
- •3.1 Introduction
- •3.2 boolean Data Type
- •3.3 Problem: A Simple Math Learning Tool
- •3.4 if Statements
- •3.5 Problem: Guessing Birthdays
- •3.6 Two-Way if Statements
- •3.7 Nested if Statements
- •3.8 Common Errors in Selection Statements
- •3.9 Problem: An Improved Math Learning Tool
- •3.10 Problem: Computing Body Mass Index
- •3.11 Problem: Computing Taxes
- •3.12 Logical Operators
- •3.13 Problem: Determining Leap Year
- •3.14 Problem: Lottery
- •3.15 switch Statements
- •3.16 Conditional Expressions
- •3.17 Formatting Console Output
- •3.18 Operator Precedence and Associativity
- •3.19 (GUI) Confirmation Dialogs
- •4.1 Introduction
- •4.2 The while Loop
- •4.3 The do-while Loop
- •4.4 The for Loop
- •4.5 Which Loop to Use?
- •4.6 Nested Loops
- •4.7 Minimizing Numeric Errors
- •4.8 Case Studies
- •4.9 Keywords break and continue
- •4.10 (GUI) Controlling a Loop with a Confirmation Dialog
- •5.1 Introduction
- •5.2 Defining a Method
- •5.3 Calling a Method
- •5.4 void Method Example
- •5.5 Passing Parameters by Values
- •5.6 Modularizing Code
- •5.7 Problem: Converting Decimals to Hexadecimals
- •5.8 Overloading Methods
- •5.9 The Scope of Variables
- •5.10 The Math Class
- •5.11 Case Study: Generating Random Characters
- •5.12 Method Abstraction and Stepwise Refinement
- •6.1 Introduction
- •6.2 Array Basics
- •6.3 Problem: Lotto Numbers
- •6.4 Problem: Deck of Cards
- •6.5 Copying Arrays
- •6.6 Passing Arrays to Methods
- •6.7 Returning an Array from a Method
- •6.8 Variable-Length Argument Lists
- •6.9 Searching Arrays
- •6.10 Sorting Arrays
- •6.11 The Arrays Class
- •7.1 Introduction
- •7.2 Two-Dimensional Array Basics
- •7.3 Processing Two-Dimensional Arrays
- •7.4 Passing Two-Dimensional Arrays to Methods
- •7.5 Problem: Grading a Multiple-Choice Test
- •7.6 Problem: Finding a Closest Pair
- •7.7 Problem: Sudoku
- •7.8 Multidimensional Arrays
- •8.1 Introduction
- •8.2 Defining Classes for Objects
- •8.3 Example: Defining Classes and Creating Objects
- •8.4 Constructing Objects Using Constructors
- •8.5 Accessing Objects via Reference Variables
- •8.6 Using Classes from the Java Library
- •8.7 Static Variables, Constants, and Methods
- •8.8 Visibility Modifiers
- •8.9 Data Field Encapsulation
- •8.10 Passing Objects to Methods
- •8.11 Array of Objects
- •9.1 Introduction
- •9.2 The String Class
- •9.3 The Character Class
- •9.4 The StringBuilder/StringBuffer Class
- •9.5 Command-Line Arguments
- •9.6 The File Class
- •9.7 File Input and Output
- •9.8 (GUI) File Dialogs
- •10.1 Introduction
- •10.2 Immutable Objects and Classes
- •10.3 The Scope of Variables
- •10.4 The this Reference
- •10.5 Class Abstraction and Encapsulation
- •10.6 Object-Oriented Thinking
- •10.7 Object Composition
- •10.8 Designing the Course Class
- •10.9 Designing a Class for Stacks
- •10.10 Designing the GuessDate Class
- •10.11 Class Design Guidelines
- •11.1 Introduction
- •11.2 Superclasses and Subclasses
- •11.3 Using the super Keyword
- •11.4 Overriding Methods
- •11.5 Overriding vs. Overloading
- •11.6 The Object Class and Its toString() Method
- •11.7 Polymorphism
- •11.8 Dynamic Binding
- •11.9 Casting Objects and the instanceof Operator
- •11.11 The ArrayList Class
- •11.12 A Custom Stack Class
- •11.13 The protected Data and Methods
- •11.14 Preventing Extending and Overriding
- •12.1 Introduction
- •12.2 Swing vs. AWT
- •12.3 The Java GUI API
- •12.4 Frames
- •12.5 Layout Managers
- •12.6 Using Panels as Subcontainers
- •12.7 The Color Class
- •12.8 The Font Class
- •12.9 Common Features of Swing GUI Components
- •12.10 Image Icons
- •13.1 Introduction
- •13.2 Exception-Handling Overview
- •13.3 Exception-Handling Advantages
- •13.4 Exception Types
- •13.5 More on Exception Handling
- •13.6 The finally Clause
- •13.7 When to Use Exceptions
- •13.8 Rethrowing Exceptions
- •13.9 Chained Exceptions
- •13.10 Creating Custom Exception Classes
- •14.1 Introduction
- •14.2 Abstract Classes
- •14.3 Example: Calendar and GregorianCalendar
- •14.4 Interfaces
- •14.5 Example: The Comparable Interface
- •14.6 Example: The ActionListener Interface
- •14.7 Example: The Cloneable Interface
- •14.8 Interfaces vs. Abstract Classes
- •14.9 Processing Primitive Data Type Values as Objects
- •14.10 Sorting an Array of Objects
- •14.11 Automatic Conversion between Primitive Types and Wrapper Class Types
- •14.12 The BigInteger and BigDecimal Classes
- •14.13 Case Study: The Rational Class
- •15.1 Introduction
- •15.2 Graphical Coordinate Systems
- •15.3 The Graphics Class
- •15.4 Drawing Strings, Lines, Rectangles, and Ovals
- •15.5 Case Study: The FigurePanel Class
- •15.6 Drawing Arcs
- •15.7 Drawing Polygons and Polylines
- •15.8 Centering a String Using the FontMetrics Class
- •15.9 Case Study: The MessagePanel Class
- •15.10 Case Study: The StillClock Class
- •15.11 Displaying Images
- •15.12 Case Study: The ImageViewer Class
- •16.1 Introduction
- •16.2 Event and Event Source
- •16.3 Listeners, Registrations, and Handling Events
- •16.4 Inner Classes
- •16.5 Anonymous Class Listeners
- •16.6 Alternative Ways of Defining Listener Classes
- •16.7 Problem: Loan Calculator
- •16.8 Window Events
- •16.9 Listener Interface Adapters
- •16.10 Mouse Events
- •16.11 Key Events
- •16.12 Animation Using the Timer Class
- •17.1 Introduction
- •17.2 Buttons
- •17.3 Check Boxes
- •17.4 Radio Buttons
- •17.5 Labels
- •17.6 Text Fields
- •17.7 Text Areas
- •17.8 Combo Boxes
- •17.9 Lists
- •17.10 Scroll Bars
- •17.11 Sliders
- •17.12 Creating Multiple Windows
- •18.1 Introduction
- •18.2 Developing Applets
- •18.3 The HTML File and the <applet> Tag
- •18.4 Applet Security Restrictions
- •18.5 Enabling Applets to Run as Applications
- •18.6 Applet Life-Cycle Methods
- •18.7 Passing Strings to Applets
- •18.8 Case Study: Bouncing Ball
- •18.9 Case Study: TicTacToe
- •18.10 Locating Resources Using the URL Class
- •18.11 Playing Audio in Any Java Program
- •18.12 Case Study: Multimedia Animations
- •19.1 Introduction
- •19.2 How is I/O Handled in Java?
- •19.3 Text I/O vs. Binary I/O
- •19.4 Binary I/O Classes
- •19.5 Problem: Copying Files
- •19.6 Object I/O
- •19.7 Random-Access Files
- •20.1 Introduction
- •20.2 Problem: Computing Factorials
- •20.3 Problem: Computing Fibonacci Numbers
- •20.4 Problem Solving Using Recursion
- •20.5 Recursive Helper Methods
- •20.6 Problem: Finding the Directory Size
- •20.7 Problem: Towers of Hanoi
- •20.8 Problem: Fractals
- •20.9 Problem: Eight Queens
- •20.10 Recursion vs. Iteration
- •20.11 Tail Recursion
- •APPENDIXES
- •INDEX
666 Chapter 19 Binary I/O
1 2 3 4 5 John Jim Jake
Lines 15–16 write two arrays into file array.dat. Lines 25–26 read three arrays back in the same order they were written. Since readObject() returns Object, casting is used to cast the objects into int[] and String[].
19.7 Random-Access Files
read-only
write-only
sequential
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 written to at random locations.
The RandomAccessFile class implements the DataInput and DataOutput interfaces, as shown in Figure 19.16. The DataInput interface shown in Figure 19.9 defines the methods (e.g., readInt, readDouble, readChar, readBoolean, readUTF) for reading primitive type values and strings, and the DataOutput interface shown in Figure 19.10 defines the methods (e.g., writeInt, writeDouble, writeChar, writeBoolean, writeUTF) for writing primitive type values and strings.
«interface» |
|
|
«interface» |
|
|
java.io.DataInput |
|
|
java.io.DataOutput |
|
|
|
|
|
|
||
java.io.RandomAccessFile |
|
|
|||
|
|
|
|
||
+RandomAccessFile(file: File, mode: |
|
Creates a RandomAccessFile stream with the specified File object |
|||
String) |
|
|
and mode. |
||
+RandomAccessFile(name: String, |
|
Creates a RandomAccessFile stream with the specified file name, |
|||
mode: String) |
|
|
string, and mode. |
||
+close(): void |
|
|
Closes the stream and releases the resource associated with it. |
||
+getFilePointer(): long |
|
Returns the offset, in bytes, from the beginning of the file to where the |
|||
|
|
|
|
|
next read or write occurs. |
+length(): long |
|
|
Returns the length of this file. |
||
+read(): int |
|
|
Reads a byte of data from this file and returns –1 at the end of stream. |
||
+read(b: byte[]): int |
|
|
Reads up to b.length bytes of data from this file into an array of bytes. |
||
+read(b: byte[], off: int, len: int): int |
|
Reads up to len bytes of data from this file into an array of bytes. |
|||
+seek(pos: long): void |
|
|
Sets the offset (in bytes specified in pos) from the beginning of the |
||
|
|
|
|
|
stream to where the next read or write occurs. |
+setLength(newLength: long): void |
|
Sets a new length for this file. |
|||
+skipBytes(int n): int |
|
|
Skips over n bytes of input. |
||
+write(b: byte[]): void |
|
Writes b.length bytes from the specified byte array to this file, |
|||
|
|
|
|
|
starting at the current file pointer. |
+write(b: byte[], off: int, len: int): |
|
Writes len bytes from the specified byte array, starting at offset off, |
|||
void |
|
|
to this file. |
||
|
|
|
|
|
|
FIGURE 19.16 RandomAccessFile implements the DataInput and DataOutput interfaces with additional methods to support random access.
When creating a RandomAccessFile, you can specify one of two modes (“r” or “rw”). Mode “r” means that the stream is read-only, and mode “rw” indicates that the stream allows
19.7 Random-Access Files 667
both read and write. For example, the following statement creates a new stream, raf, that allows the program to read from and write to the file test.dat:
RandomAccessFile raf = new RandomAccessFile("test.dat", "rw");
If test.dat already exists, raf is created to access it; if test.dat does not exist, a new file named test.dat is created, and raf is created to access the new file. The method raf.length() returns the number of bytes in test.dat at any given time. If you append new data into the file, raf.length() increases.
Tip
If the file is not intended to be modified, open it with the "r" mode. This prevents unintentional modification of the file.
A random-access file consists of a sequence of bytes. A special marker called a file pointer is
file pointer
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 is set at the beginning of the file. When you read or write data to the file, the file pointer moves forward to the next data item. For example, if you read an int value using readInt(), the JVM reads 4 bytes from the file pointer, and now the file pointer is 4 bytes ahead of the previous location, as shown in Figure 19.17.
|
|
|
|
|
|
File pointer |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
File |
|
|
byte |
|
byte |
… |
byte |
byte |
byte |
byte |
byte |
|
… |
byte |
byte |
byte |
byte |
byte |
(a) Before readInt() |
|
|||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
File pointer |
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(b) After readInt() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
File |
|
|
byte |
|
byte |
… |
byte |
byte |
byte |
byte |
byte |
|
… |
byte |
byte |
byte |
byte |
byte |
|
|
|||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FIGURE 19.17 After an int value is read, the file pointer is moved 4 bytes ahead.
For a RandomAccessFile raf, you can use the raf.seek(position) method to move the file pointer to a specified position. raf.seek(0) moves it to the beginning of the file, and raf.seek(raf.length()) moves it to the end of the file. Listing 19.8 demonstrates RandomAccessFile. A large case study of using RandomAccessFile to organize an address book is given in Supplement VII.B.
LISTING 19.8 TestRandomAccessFile.java
1 import java.io.*;
2
3 public class TestRandomAccessFile {
4 public static void main(String[] args) throws IOException {
5// Create a random-access file
6 |
RandomAccessFile inout = new RandomAccessFile("inout.dat", "rw"); |
RandomAccessFile |
7 |
|
|
8// Clear the file to destroy the old contents, if any
9 |
inout.setLength(0); |
empty file |
10 |
|
|
11// Write new integers to the file
12for (int i = 0; i < 200; i++)
13 |
inout.writeInt(i); |
write |
14 |
|
|
15// Display the current length of the file
16System.out.println("Current file length is " + inout.length() );
668 Chapter 19 |
Binary I/O |
||||||||||||||||
|
18 |
|
// Retrieve the first number |
||||||||||||||
move pointer |
19 |
|
inout.seek(0); |
// Move the file pointer to the beginning |
|||||||||||||
read |
20 |
|
System.out.println("The first number is " + |
inout.readInt() |
); |
||||||||||||
|
21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
// Retrieve the second number |
||||||||||||||
|
23 |
|
inout.seek(1 * 4); |
// Move the file pointer to the second number |
|||||||||||||
|
24 |
|
System.out.println("The second number is " + |
inout.readInt() |
); |
||||||||||||
|
25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
// Retrieve the tenth number |
||||||||||||||
|
27 |
|
inout.seek(9 * 4); |
// Move the file pointer to the tenth number |
|||||||||||||
|
28 |
|
System.out.println("The tenth number is " + |
inout.readInt() |
); |
||||||||||||
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
|
// Modify the eleventh number |
||||||||||||||
|
31 |
|
inout.writeInt(555); |
|
|
|
|
|
|||||||||
|
32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
|
// Append a new number |
||||||||||||||
|
34 |
|
inout.seek(inout.length()); |
// Move the file pointer to the end |
|||||||||||||
|
35 |
|
inout.writeInt(999); |
|
|
|
|
|
|
||||||||
|
36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
// Display the new length |
||||||||||||||
|
38 |
|
System.out.println("The new length is " + |
inout.length() |
); |
|
|
||||||||||
|
39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
|
// Retrieve the new eleventh number |
||||||||||||||
|
41 |
|
inout.seek(10 * 4); |
|
// Move the file pointer to the next number |
||||||||||||
|
42 |
|
System.out.println("The eleventh number is " + |
inout.readInt() |
); |
||||||||||||
|
43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
close file |
44 |
|
inout.close(); |
||||||||||||||
|
45 |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Current file length is 800
The first number is 0
The second number is 1
The tenth number is 9
The new length is 804
The eleventh number is 555
A RandomAccessFile is created for the file named inout.dat with mode “rw” to allow both read and write operations in line 6.
inout.setLength(0) sets the length to 0 in line 9. This, in effect, destroys the old contents of the file.
The for loop writes 200 int values from 0 to 199 into the file in lines 12–13. Since each int value takes 4 bytes, the total length of the file returned from inout.length() is now 800 (line 16), as shown in sample output.
Invoking inout.seek(0) in line 19 sets the file pointer to the beginning of the file. inout.readInt() reads the first value in line 20 and moves the file pointer to the next number. The second number is read in line 23.
inout.seek(9 * 4) (line 27) moves the file pointer to the tenth number. inout
.readInt() reads the tenth number and moves the file pointer to the eleventh number in line 28. inout.write(555) writes a new eleventh number at the current position (line 31). The previous eleventh number is destroyed.
inout.seek(inout.length()) moves the file pointer to the end of the file (line 34). inout.writeInt(999) writes a 999 to the file. Now the length of the file is increased by 4, so inout.length() returns 804 (line 38).
inout.seek(10 * 4) moves the file pointer to the eleventh number in line 41. The new eleventh number, 555, is displayed in line 42.
Review Questions 669
KEY TERMS
binary I/O |
650 |
sequential-access file 666 |
|
deserialization 664 |
serialization 664 |
||
file pointer |
667 |
stream |
650 |
random-access file 667 |
text I/O |
650 |
CHAPTER SUMMARY
1.I/O can be classified into text I/O and binary I/O. Text I/O interprets data in sequences of characters. Binary I/O interprets data as raw binary values. How text is stored in a file depends on the encoding scheme for the file. Java automatically performs encoding and decoding for text I/O.
2.The InputStream and OutputStream classes are the roots of all binary I/O classes. FileInputStream/FileOutputStream associates a file for binary input/output.
BufferedInputStream/BufferedOutputStream can be used to wrap on any binary I/O stream to improve performance. DataInputStream/DataOutputStream can be used to read/write primitive values and strings.
3.ObjectInputStream/ObjectOutputStream can be used to read/write objects in addition to primitive values and strings. To enable object serialization, the object’s defining class must implement the java.io.Serializable marker interface.
4.The RandomAccessFile class enables you to read and write data to a file. You can open a file with the “r” mode to indicate that it is read-only, or with the “rw” mode to indicate that it is updateable. Since the RandomAccessFile class implements
DataInput and DataOutput interfaces, many methods in RandomAccessFile are the same as those in DataInputStream and DataOutputStream.
REVIEW QUESTIONS
Sections 19.1–19.2
19.1What is a text file, and what is a binary file? Can you view a text file or a binary file using a text editor?
19.2How do you read or write data in Java? What is a stream?
Section 19.3
19.3What are the differences between text I/O and binary I/O?
19.4How is a Java character represented in the memory, and how is a character represented in a text file?
19.5If you write string “ABC” to an ASCII text file, what values are stored in the file?
19.6If you write string “100” to an ASCII text file, what values are stored in the file? If you write a numeric byte-type value 100 using binary I/O, what values are stored in the file?
19.7What is the encoding scheme for representing a character in a Java program? By default, what is the encoding scheme for a text file on Windows?
Section 19.4
19.8Why do you have to declare to throw IOException in the method or use a trycatch block to handle IOException for Java IO programs?
19.9Why should you always close streams?
670 Chapter 19 Binary I/O
19.10InputStream reads bytes. Why does the read() method return an int instead of a byte? Find the abstract methods in InputStream and OutputStream.
19.11Does FileInputStream/FileOutputStream introduce any new methods? How do you create a FileInputStream/FileOutputStream?
19.12What will happen if you attempt to create an input stream on a nonexistent file? What will happen if you attempt to create an output stream on an existing file? Can you append data to an existing file?
19.13How do you append data to an existing text file using java.io.PrintWriter?
19.14Suppose a file contains an unspecified number of double values. Theses values were written to the file using the writeDouble method using a DataOutputStream. How do you write a program to read all these values? How do you detect the end of file?
19.15What is written to a file using writeByte(91) on a FileOutputStream?
19.16How do you check the end of a file in a binary input stream (FileInputStream,
DataInputStream)?
19.17What is wrong in the following code?
import java.io.*;
public class Test {
public static void main(String[] args) { try {
FileInputStream fis = new FileInputStream("test.dat");
}
catch (IOException ex) { ex.printStackTrace();
}
catch (FileNotFoundException ex) { ex.printStackTrace();
}
}
}
19.18Suppose you run the program on Windows using the default ASCII encoding. After the program is finished, how many bytes are in the file t.txt? Show the contents of each byte.
public class Test {
public static void main(String[] args) throws java.io.IOException {
java.io.PrintWriter output =
new java.io.PrintWriter("t.txt"); output.printf("%s", "1234"); output.printf("%s", "5678"); output.close();
}
}
19.19After the program is finished, how many bytes are in the file t.dat? Show the contents of each byte.
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException { DataOutputStream output = new DataOutputStream(
Review Questions 671
new FileOutputStream("t.dat")); output.writeInt(1234); output.writeInt(5678); output.close();
}
}
19.20For each of the following statements on a DataOutputStream out, how many bytes are sent to the output?
output.writeChar('A'); output.writeChars("BC"); output.writeUTF("DEF");
19.21What are the advantages of using buffered streams? Are the following statements correct?
BufferedInputStream input1 =
new BufferedInputStream(new FileInputStream("t.dat"));
DataInputStream input2 = new DataInputStream(
new BufferedInputStream(new FileInputStream("t.dat")));
ObjectInputStream input3 = new ObjectInputStream(
new BufferedInputStream(new FileInputStream("t.dat")));
Section 19.6
19.22What types of objects can be stored using the ObjectOutputStream? What is the method for writing an object? What is the method for reading an object? What is the return type of the method that reads an object from ObjectInputStream?
19.23If you serialize two objects of the same type, will they take the same amount of space? If not, give an example.
19.24Is it true that any instance of java.io.Serializable can be successfully serialized? Are the static variables in an object serialized? How do you mark an instance variable not to be serialized?
19.25Can you write an array to an ObjectOutputStream?
19.26Is it true that DataInputStream/DataOutputStream can always be replaced by ObjectInputStream/ObjectOutputStream?
19.27What will happen when you attempt to run the following code?
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException { ObjectOutputStream output =
new ObjectOutputStream(new FileOutputStream("object.dat"));
output.writeObject(new A());
}
}
class A implements Serializable { B b = new B();
}
class B {
}
672 Chapter 19 Binary I/O
Section 19.7
19.28Can RandomAccessFile streams read and write a data file created by
DataOutputStream? Can RandomAccessFile streams read and write objects?
19.29Create a RandomAccessFile stream for the file address.dat to allow the updating of student information in the file. Create a DataOutputStream for the file address.dat. Explain the differences between these two statements.
19.30What happens if the file test.dat does not exist when you attempt to compile and run the following code?
import java.io.*;
public class Test {
public static void main(String[] args) { try {
RandomAccessFile raf =
new RandomAccessFile("test.dat", "r"); int i = raf.readInt();
}
catch (IOException ex) { System.out.println("IO exception");
}
}
}
PROGRAMMING EXERCISES
Section 19.3
19.1* (Creating a text file) Write a program to create a file named Exercise19_1.txt if it does not exist. Append new data to it. Write 100 integers created randomly into the file using text I/O. Integers are separated by a space.
Section 19.4
19.2* (Creating a binary data file) Write a program to create a file named Exercise19_2.dat if it does not exist. Append new data to it. Write 100 integers created randomly into the file using binary I/O.
19.3* (Summing all the integers in a binary data file) Suppose a binary data file named
Exercise19_3.dat has been created using writeInt(int) in DataOutputStream. The file contains an unspecified number of integers. Write a program to find the sum of integers.
19.4* (Converting a text file into UTF) Write a program that reads lines of characters from a text and writes each line as a UTF-8 string into a binary file. Display the sizes of the text file and the binary file. Use the following command to run the program:
java Exercise19_4 Welcome.java Welcome.utf
Section 19.6
19.5* (Storing objects and arrays into a file) Write a program that stores an array of five int values 1, 2, 3, 4 and 5, a Date object for current time, and a double value 5.5 into the file named Exercise19_5.dat.
Programming Exercises 673
19.6* (Storing Loan objects) The Loan class, in Listing 10.2, does not implement Serializable. Rewrite the Loan class to implement Serializable. Write a program that creates five Loan objects and stores them in a file named
Exercise19_6.dat.
19.7* (Restoring objects from a file) Suppose a file named Exercise19_7.dat has been created using the ObjectOutputStream. The file contains Loan objects. The Loan class, in Listing 10.2, does not implement Serializable. Rewrite the Loan class to implement Serializable. Write a program that reads the Loan objects from the file and computes the total loan amount. Suppose you don’t know how many Loan objects are in the file. Use EOFException to end the loop.
Section 19.7
19.8* (Updating count) Suppose you want to track how many times a program has been executed. You may store an int to count the file. Increase the count by 1 each time this program is executed. Let the program be Exercise19_8 and store the count in Exercise19_8.dat.
19.9*** (Address book) Supplement VII.B gives a case study of using random-access files for creating and manipulating an address book. Modify the case study by adding an Update button, as shown in Figure 19.18, to enable the user to modify the address that is being displayed.
FIGURE 19.18 The application can store, retrieve, and update addresses from a file.
Comprehensive
19.10* (Splitting files) Suppose you wish to back up a huge file (e.g., a 10-GB AVI file) to a CD-R. You can achieve it by splitting the file into smaller pieces and backing up these pieces separately. Write a utility program that splits a large file into smaller ones using the following command:
java Exercise19_10 SourceFile numberOfPieces
The command creates files SourceFile.1, SourceFile.2, Á , SourceFile.n, where n is numberOfPieces and the output files are about the same size.
19.11** (Splitting files GUI) Rewrite Exercise 19.10 with a GUI, as shown in Figure 19.19(a).
Video Note
Split a large file
(a) |
(b) |
FIGURE 19.19 (a) The program splits a file. (b) The program combines files into a new file.
674 Chapter 19 Binary I/O
19.12* (Combining files) Write a utility program that combines the files together into a new file using the following command:
java Exercise19_12 SourceFile1 Á SoureFilen TargetFile
The command combines SourceFile1, Á , and SourceFilen into TargetFile. 19.13* (Combining files GUI) Rewrite Exercise 19.12 with a GUI, as shown in Figure
19.19(b).
19.14(Encrypting files) Encode the file by adding 5 to every byte in the file. Write a program that prompts the user to enter an input file name and an output file name and saves the encrypted version of the input file to the output file.
19.15(Decrypting files) Suppose a file is encrypted using the scheme in Exercise 19.14. Write a program to decode an encrypted file. Your program should prompt the user to enter an input file name and an output file name and should save the unencrypted version of the input file to the output file.
19.16(Frequency of characters) Write a program that prompts the user to enter the name of an ASCII text file and display the frequency of the characters in the file.
19.17** (BitOutputStream) Implement a class named BitOutputStream, as shown in Figure 19.20, for writing bits to an output stream. The writeBit(char bit) method stores the bit in a byte variable. When you create a BitOutputStream, the byte is empty. After invoking writeBit('1'), the byte becomes 00000001. After invoking writeBit("0101"), the byte becomes 00010101. The first three bits are not filled yet. When a byte is full, it is sent to the output stream. Now the byte is reset to empty. You must close the stream by invoking the close() method. If the byte is not empty and not full, the close() method first fills the zeros to make a full 8 bits in the byte, and then output the byte and close the stream. For a hint, see Exercise 4.46. Write a test program that sends the bits 010000100100001001101 to the file named
Exercise19_17.dat.
BitOutputStream
+BitOutputStream(file: File)
+writeBit(char bit): void
+writeBit(String bit): void
+close(): void
FIGURE 19.20 BitOutputStream outputs a stream of bits to a file.
19.18* (View bits) Write the following method that displays the bit representation for the last byte in an integer:
public static String getBits(int value)
For a hint, see Exercise 4.46. Write a program that prompts the user to enter a file name, reads bytes from a file, and displays each byte’s binary representation.
19.19* (View hex) Write a program that prompts the user to enter a file name, reads bytes from a file, and displays each byte’s hex representation. (Hint: You may first convert the byte value into an 8-bit string, then convert the bit string into a two-digit hex string.)
Programming Exercises 675
19.20** (Binary Editor) Write a GUI application that lets the user enter a file name in the text field and press the Enter key to display its binary representation in a text area. The user can also modify the binary code and save it back to the file, as shown in Figure 19.21(a).
(a) |
(b) |
FIGURE 19.21 The exercises enable the user to manipulate the contents of the file in binary and hex.
19.21** (Hex Editor) Write a GUI application that lets the user enter a file name in the text field and press the Enter key to display its hex representation in a text area. The user can also modify the hex code and save it back to the file, as shown in Figure 19.21(b).
This page intentionally left blank
CHAPTER 20
RECURSION
Objectives
■To describe what a recursive method is and the benefits of using recursion (§20.1).
■To develop recursive methods for recursive mathematical functions (§§20.2–20.3).
■To explain how recursive method calls are handled in a call stack (§§20.2–20.3).
■To use an overloaded helper method to derive a recursive method (§20.5).
■To solve selection sort using recursion (§20.5.1).
■To solve binary search using recursion (§20.5.2).
■To get the directory size using recursion (§20.6).
■To solve the Towers of Hanoi problem using recursion (§20.7).
■To draw fractals using recursion (§20.8).
■To solve the Eight Queens problem using recursion (§20.9).
■To discover the relationship and difference between recursion and iteration (§20.10).
■To know tail-recursive methods and why they are desirable (§20.11).