- •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
660 Chapter 19 Binary I/O
Video Note
Copy file
If no buffer size is specified, the default size is 512 bytes. A buffered input stream reads as many data as possible into its buffer in a single read call. By contrast, a buffered output stream calls the write method only when its buffer fills up or when the flush() method is called.
You can improve the performance of the TestDataStream program in the preceding example by adding buffers in the stream in lines 6–7 and 13–14 as follows:
DataOutputStream output = new DataOutputStream(
new BufferedOutputStream (new FileOutputStream("temp.dat")));
DataInputStream input = new DataInputStream(
new BufferedInputStream (new FileInputStream("temp.dat")));
Tip
You should always use buffered IO to speed up input and output. For small files, you may not notice performance improvements. However, for large files—over 100 MB—you will see substantial improvements using buffered IO.
19.5 Problem: Copying Files
This section develops a program that copies files. The user needs to provide a source file and a target file as command-line arguments using the following command:
java Copy source target
The program copies a source file to a target file and displays the number of bytes in the file. If the source does not exist, the user is told that the file has not been found. If the target file already exists, the user is told that the file exists. A sample run of the program is shown in Figure 19.13.
File exists
Delete file
Copy
Source does not exist
FIGURE 19.13 The program copies a file.
To copy the contents from a source to a target file, it is appropriate to use a binary input stream to read bytes from the source file and a binary output stream to send bytes to the target file, regardless of the contents of the file. The source file and the target file are specified from the command line. Create an InputFileStream for the source file and an OutputFileStream for the target file. Use the read() method to read a byte from the input stream, and then use the write(b) method to write the byte to the output stream. Use
BufferedInputStream and BufferedOutputStream to improve the performance. Listing 19.4 gives the solution to the problem.
19.5 Problem: Copying Files 661
LISTING 19.4 Copy.java
1 import java.io.*;
2
3 public class Copy {
4/** Main method
5 @param args[0] for sourcefile
6@param args[1] for target file
7*/
8 public static void main(String[] args) throws IOException {
9// Check command-line parameter usage
10 |
if (args.length != 2) { |
check usage |
11System.out.println(
12"Usage: java Copy sourceFile targetfile");
13System.exit(0);
14}
15 |
|
|
16 |
// Check whether source file exists |
|
17 |
File sourceFile = new File(args[0]); |
source file |
18if (!sourceFile.exists()) {
19System.out.println("Source file " + args[0] + " not exist");
20System.exit(0);
21}
22 |
|
|
|
23 |
// Check whether target file exists |
|
|
24 |
|
File targetFile = new File(args[1]); |
target file |
25if (targetFile.exists()) {
26System.out.println("Target file " + args[1] + " already
27exists");
28System.exit(0);
29}
30 |
|
|
|
|
|
|
|
31 |
// Create an input stream |
|
|||||
32 |
|
BufferedInputStream input = |
|
input stream |
|||
33 |
|
|
new BufferedInputStream(new FileInputStream(sourceFile)); |
|
|
||
34 |
|
|
|
|
|
|
|
35 |
// Create an output stream |
|
|||||
36 |
|
BufferedOutputStream output = |
|
|
output stream |
||
37 |
|
|
new BufferedOutputStream(new FileOutputStream(targetFile)); |
|
|||
38 |
|
|
|
|
|
|
|
39// Continuously read a byte from input and write it to output
40int r; int numberOfBytesCopied = 0;
41 |
while ((r = input.read() |
) != -1) { |
read |
|
42 |
|
output.write((byte)r); |
|
write |
43numberOfBytesCopied++;
44}
45 |
|
|
46 |
// Close streams |
|
47 |
input.close(); |
close stream |
48 |
output.close(); |
|
49 |
|
|
50// Display the file size
51System.out.println(numberOfBytesCopied + " bytes copied");
52}
53}
The program first checks whether the user has passed two required arguments from the command line in lines 10–14.
The program uses the File class to check whether the source file and target file exist. If the source file does not exist (lines 18–21) or if the target file already exists, exit the program.
662 Chapter 19 Binary I/O
Video Note
Object I/O
An input stream is created using BufferedInputStream wrapped on FileInputStream in lines 32–33, and an output stream is created using BufferedOutputStream wrapped on
FileOutputStream in lines 36–37.
The expression ((r = input.read()) != -1) (line 41) reads a byte from input. read(), assigns it to r, and checks whether it is –1. The input value of –1 signifies the end of a file. The program continuously reads bytes from the input stream and sends them to the output stream until all of the bytes have been read.
19.6 Object I/O
DataInputStream/DataOutputStream enables you to perform I/O for primitive type values and strings. ObjectInputStream/ObjectOutputStream enables you to perform I/O for objects in addition to primitive type values and strings. Since ObjectInputStream/ ObjectOutputStream contains all the functions of
DataOutputStream, you can replace DataInputStream/DataOutputStream completely with ObjectInputStream/ObjectOutputStream.
ObjectInputStream extends InputStream and implements ObjectInput and
ObjectStreamConstants, as shown in Figure 19.14. ObjectInput is a subinterface of
DataInput. DataInput is shown in Figure 19.9. ObjectStreamConstants contains the constants to support ObjectInputStream/ObjectOutputStream.
|
«interface» |
|
|
ObjectStreamConstants |
|
java.io.InputStream |
|
|
|
«interface» |
|
|
java.io.DataInput |
|
java.io.ObjectInputStream |
«interface» |
|
java.io.ObjectInput |
||
|
||
+ObjectInputStream(in: InputStream) |
+readObject(): Object |
FIGURE 19.14 ObjectInputStream can read objects, primitive type values, and strings.
ObjectOutputStream extends OutputStream and implements ObjectOutput and
ObjectStreamConstants, as shown in Figure 19.15. ObjectOutput is a subinterface of DataOutput. DataOutput is shown in Figure 19.10.
|
|
|
|
«interface» |
|
|
|
|
|
|
ObjectStreamConstants |
|
|
|
java.io.OutputStream |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
«interface» |
|
|
|
|
|
|
java.io.DataOutput |
|
|
|
|
|
|
|
|
|
|
java.io.ObjectOutputStream |
|
«interface» |
|
|
|
|
|
java.io.ObjectOutput |
|
|
||
|
|
|
|
|
|
|
+ObjectOutputStream(out: OutputStream) |
|
+writeObject(o: Object): void |
|
Writes an object. |
||
|
|
|
|
|
|
|
FIGURE 19.15 ObjectOutputStream can write objects, primitive type values, and strings.
19.6 Object I/O 663
You may wrap an ObjectInputStream/ObjectOutputStream on any InputStream/
OutputStream using the following constructors:
// Create an ObjectInputStream
public ObjectInputStream(InputStream in)
// Create an ObjectOutputStream
public ObjectOutputStream(OutputStream out)
Listing 19.5 writes student names, scores, and current date to a file named object.dat.
LISTING 19.5 TestObjectOutputStream.java
1 import java.io.*;
2
3 public class TestObjectOutputStream {
4 public static void main(String[] args) throws IOException {
5 // Create an output stream for file object.dat
6ObjectOutputStream output =
7 new ObjectOutputStream(new FileOutputStream("object.dat"));
8
9// Write a string, double value, and object to the file
10output.writeUTF("John");
11output.writeDouble(85.5);
12output.writeObject(new java.util.Date());
13
14// Close output stream
15output.close();
16}
17}
output stream
output
An ObjectOutputStream is created to write data into file object.dat in lines 6–7. A string, a double value, and an object are written to the file in lines 10–12. To improve performance, you may add a buffer in the stream using the following statement to replace lines 6–7:
ObjectOutputStream output = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream("object.dat")));
Multiple objects or primitives can be written to the stream. The objects must be read back from the corresponding ObjectInputStream with the same types and in the same order as they were written. Java’s safe casting should be used to get the desired type. Listing 19.6 reads data back from object.dat.
LISTING 19.6 TestObjectInputStream.java
1 import java.io.*;
2
3 public class TestObjectInputStream {
4public static void main(String[] args)
5 throws ClassNotFoundException, IOException {
6// Create an input stream for file object.dat
7 |
|
ObjectInputStream input = |
|
input stream |
|
8 |
|
|
new ObjectInputStream(new FileInputStream("object.dat")); |
|
|
9 |
|
|
|
|
|
10 |
// Write a string, double value, and object to the file |
|
|||
11 |
String name = input.readUTF(); |
input |
12double score = input.readDouble();
13java.util.Date date = (java.util.Date)(input.readObject());
14System.out.println(name + " " + score + " " + date);
15
664 Chapter 19 Binary I/O
|
|
|
|
16 |
// Close output stream |
|
|
|
|
|
17 |
input.close(); |
|
|
|
|
|
18 |
} |
|
|
|
|
|
19 } |
||
|
|
|
|
|
|
|
|
|
|
|
|
John 85.5 Mon Jun 26 17:17:29 EDT 2006 |
|
|
|
|
|
|
||
|
|
|
|
|
|
|
ClassNotFoundException |
|
The readObject() method may throw java.lang. ClassNotFoundException. The reason |
||||
|
|
|
|
|
is that when the JVM restores an object, it first loads the class for the object if the class has not |
|
|
|
|
|
|
been loaded. Since ClassNotFoundException is a checked exception, the main method |
|
|
|
|
|
|
declares to throw it in line 5. An ObjectInputStream is created to read input from object.dat in |
|
|
|
|
|
|
lines 7–8. You have to read the data from the file in the same order and format as they were written |
|
|
|
|
|
|
to the file. A string, a double value, and an object are read in lines 11–13. Since readObject() |
|
|
|
|
|
|
returns an Object, it is cast into Date and assigned to a Date variable in line 13. |
|
|
|
|
|
|
19.6.1 The Serializable Interface |
|
|
|
|
|
|
Not every object can be written to an output stream. Objects that can be so written are said to |
|
serializable |
|
be serializable. A serializable object is an instance of the java.io.Serializable inter- |
||||
|
|
|
|
|
face, so the object’s class must implement Serializable. |
|
|
|
|
|
|
|
The Serializable interface is a marker interface. Since it has no methods, you don’t need to |
|
|
|
|
|
add additional code in your class that implements Serializable. Implementing this interface |
|
|
|
|
|
|
enables the Java serialization mechanism to automate the process of storing objects and arrays. |
|
|
|
|
|
|
|
To appreciate this automation feature, consider what you otherwise need to do in order to |
|
|
|
|
|
store an object. Suppose you want to store a JButton object. To do this you need to store all |
|
|
|
|
|
|
the current values of the properties (e.g., color, font, text, alignment) in the object. Since |
|
|
|
|
|
|
JButton is a subclass of AbstractButton, the property values of AbstractButton have |
|
|
|
|
|
|
to be stored as well as the properties of all the superclasses of AbstractButton. If a prop- |
|
|
|
|
|
|
erty is of an object type (e.g., background of the Color type), storing it requires storing all |
|
|
|
|
|
|
the property values inside this object. As you can see, this is a very tedious process. Fortu- |
|
|
|
|
|
|
nately, you don’t have to go through it manually. Java provides a built-in mechanism to auto- |
|
serialization |
|
mate the process of writing objects. This process is referred to as object serialization, which |
||||
|
|
|
|
|
is implemented in ObjectOutputStream. In contrast, the process of reading objects is |
|
deserialization |
|
referred to as object deserialization, which is implemented in ObjectInputStream. |
||||
|
|
|
|
|
|
Many classes in the Java API implement Serializable. The utility classes, such as |
|
|
|
|
|
java.util.Date, and all the Swing GUI component classes implement Serializable. |
|
|
|
|
|
|
Attempting to store an object that does not support the Serializable interface would cause |
|
NotSerializable- |
|
a NotSerializableException. |
||||
Exception |
|
|
When a serializable object is stored, the class of the object is encoded; this includes the class |
|||
|
|
|
|
|
name and the signature of the class, the values of the object’s instance variables, and the closure |
|
|
|
|
|
|
of any other objects referenced from the initial object. The values of the object’s static variables |
|
|
|
|
|
|
are not stored. |
|
|
|
|
|
|
|
Note |
|
|
|
|
|
|
nonserializable fields |
|
|
|
|
|
|
If an object is an instance of Serializable but contains nonserializable instance data fields, |
|
|
|
|
|
|
can it be serialized? The answer is no. To enable the object to be serialized, mark these data fields |
transient |
|
|
with the transient keyword to tell the JVM to ignore them when writing the object to an |
|||
|
|
|
|
|
|
object stream. Consider the following class: |
public class Foo implements java.io.Serializable { private int v1;
private static double v2; private transient A v3 = new A();
}
class A { } // A is not serializable
19.6 Object I/O 665
When an object of the Foo class is serialized, only variable v1 is serialized. Variable v2 is not serialized because it is a static variable, and variable v3 is not serialized because it is marked transient. If v3 were not marked transient, a java.io.NotSerializableException would occur.
Note
duplicate objects
If an object is written to an object stream more than once, will it be stored in multiple copies? No, it will not. When an object is written for the first time, a serial number is created for it. The JVM writes the complete content of the object along with the serial number into the object stream. After the first time, only the serial number is stored if the same object is written again. When the objects are read back, their references are the same, since only one object is actually created in the memory.
19.6.2Serializing Arrays
An array is serializable if all its elements are serializable. An entire array can be saved using writeObject into a file and later can be restored using readObject. Listing 19.7 stores an array of five int values and an array of three strings and reads them back to display on the console.
LISTING 19.7 TestObjectStreamForArray.java
1 import java.io.*;
2
3 public class TestObjectStreamForArray {
4public static void main(String[] args)
5 throws ClassNotFoundException, IOException {
6int[] numbers = {1, 2, 3, 4, 5};
7 String[] strings = {"John", "Jim", "Jake"}; 8
9 // Create an output stream for file array.dat
10ObjectOutputStream output =
11new ObjectOutputStream(new FileOutputStream
12("array.dat", true));
13
14// Write arrays to the object output stream
15output.writeObject(numbers);
16output.writeObject(strings);
17
18// Close the stream
19output.close();
20
21// Create an input stream for file array.dat
22ObjectInputStream input =
23new ObjectInputStream(new FileInputStream("array.dat"));
25int[] newNumbers = (int[])(input.readObject());
26String[] newStrings = (String[])(input.readObject());
28// Display arrays
29for (int i = 0; i < newNumbers.length; i++)
30System.out.print(newNumbers[i] + " ");
31 |
System.out.println(); |
32 |
|
33for (int i = 0; i < newStrings.length; i++)
34System.out.print(newStrings[i] + " ");
35}
36}
output stream
store array
input stream
restore array