What We Will Cover
Illuminations
Midterm Questions
Questions on Assignment?
^ top
9.1: Exception Handling Basics
Learner Outcomes
At the end of the lesson the student will be able to:
- Describe the Java syntax for exception handling
- Write code to catch and handle exceptions
- Generate code to handle user-input errors
|
^ top
9.1.1: About Exceptions
- A common way to develop a program is to first make the code work assuming that nothing unusual happens
- After the usual case works, then you start to consider the exceptional cases like:
- What if a users enter letters when you want numbers
- What if a file your program needs was moved or deleted
- Java helps you to write your code in just this way:
- You first write your code as if nothing unusual will happen
- When the usual case works correctly, you add code to handle exceptional cases
- The mechanism to handle the unusual cases is known as exception handling
- Exception handling is an important part of developing "solid" or "robust" programs
- A solid or robust program means that you can run the program day after day
- If crazy or unusual things happen, the program copes or at least recognizes that something is wrong
Terminology
- Exception: an error condition that changes the normal flow of a program
- Throw an exception: either the Java runtime or your code signals that something unusual happened
- Catch an exception: take appropriate action to deal with an exception
- Exception handler: the code that processes an exception
Example Program the Causes an Exception
1
2
3
4
5
6
|
public class ExceptionDemo {
public static void main(String[] args) {
String str = null;
System.out.println(str.length());
}
}
|
How Exceptions Work
^ top
9.1.2: Exception Example
- Many exceptions can occur because of user input errors
- As an example, let us look at how you might handle user input errors
- Following is a simple program showing the usual case
The Usual Case
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import java.util.*;
public class TotalCalculator1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double cost = 0, tax = 0;
System.out.print("Enter cost: ");
cost = input.nextDouble();
System.out.print("Enter tax: ");
tax = input.nextDouble();
double total = cost + tax;
System.out.println("Total: " + total);
System.out.println("Thanks for paying!");
}
}
|
- The program works for the usual case but can fail on invalid data
- What happens if the user enters a dollar sign before the numbers?
- What happens if the user enters letters instead of numbers?
- What if the user enters Ctrl-C
Enter cost: $100
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextDouble(Scanner.java:2387)
at TotalCalculator1.main(TotalCalculator1.java:9)
- The program prints the message shown above and then ends
- This is not desirable behavior, so we need to catch and handle the exception
- In Java, you catch and handle exceptions with a
try-catch statement
^ top
9.1.3: Handling Exceptions
Example of Exception Handling
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import java.util.*;
public class TotalCalculator2 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double cost = 0, tax = 0;
try {
System.out.print("Enter cost: ");
cost = input.nextDouble();
System.out.print("Enter tax: ");
tax = input.nextDouble();
double total = cost + tax;
System.out.println("Total: " + total);
} catch(InputMismatchException e) {
System.out.println(
"Error -- enter digits only!");
} catch(NoSuchElementException e) { // Ctrl-C
System.out.println("\nGoodbye!");
System.exit(0);
}
System.out.println("Thanks for paying!");
}
}
|
^ top
9.1.4: Exception Flow of Control
- When an exception occurs:
- The method stops processing at the point of failure
- The code creates an object with the error information
- The JVM tries to locate the exception handling code
- If the JVM finds the exception-handling code, the matching
catch block is passed the exception object
- If the JVM does not find a matching catch block, it uses the general exception handler instead
- General exception handler displays an error messages on the console like the following and then ends the program
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:819)
at java.util.Scanner.next(Scanner.java:1431)
at java.util.Scanner.nextDouble(Scanner.java:2335)
at ReceiptCalculator.main(ReceiptCalculator.java:9)
- Let us trace through the flow for our example code
- The user enters bad data and the
main() method stops processing
Enter cost: $100
- The scanner object code creates an exception object of type
InputMismatchException
- the JVM passes the exception object to the
catch statement:
catch(InputMismatchException e)
- The exception handling code executes
- The program continues with the code after the list of
catch blocks
- Note that the program does not execute the second input statement
- As soon as the error occurs, the program jumps to the exception handler
- Program execution continues after the exception handler code
^ top
9.1.5: Trying Again
- To allow the user to try again when there is an error, we need to code a loop
- One way is to use a looping statement like the following
Example of Verification Using a Loop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import java.util.*;
public class TotalCalculator3 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double cost = 0, tax = 0;
boolean more = true;
while (more) {
try {
System.out.print("Enter cost: ");
cost = input.nextDouble();
System.out.print("Enter tax: ");
tax = input.nextDouble();
double total = cost + tax;
System.out.println("Total: " + total);
more = false;
} catch(InputMismatchException e) {
System.out.println(
"Error -- enter digits only!");
input.nextLine(); // clear the buffer
} catch(NoSuchElementException e) {
System.out.println("\nGoodbye!");
System.exit(0);
}
}
System.out.println("Thanks for paying!");
}
}
|
- Running the program we see:
Enter cost: 100
Enter tax: $6
Error -- enter digits only!
Enter cost: 100
Enter tax: 6
Total: 106.0
Thanks for paying!
The program now allows the user to correct their errors and continue
However, the code requires the user to reenter all the numbers
A better solution is to reenter only the number in error
To do this we need to loop on each statement that could cause an exception
This leads to duplicate code
To eliminate the duplicate code, we use a method to handle the entire data input process
^ top
9.1.6: Verifying in Methods
- Using a method we can group our input and verification code and reduce duplication
- Running the program we see:
Enter net cost: ten
Error -- enter digits only!
Enter net cost: 10
Enter tax: $1.23
Error -- enter digits only!
Enter tax: 1.23
Total: 11.23
Thanks for paying!
Users can correct individual errors without having to redo all their entries
Also note how much simpler the code in main() appears
Example of Verification Using a Method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
import java.util.*;
public class TotalCalculator4 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double cost = 0, tax = 0;
cost = readDouble(input, "Enter cost: ");
tax = readDouble(input, "Enter tax: ");
double total = cost + tax;
System.out.println("Total: " + total);
System.out.println("Thanks for shopping!");
}
/**
* Read a double from the console.
*
* @param input Scanner object to read from.
* @param prompt User prompt to show before input
* @return A double entered by the user.
*/
public static double readDouble(Scanner input,
String prompt) {
double number = 0;
boolean more = true;
while (more) {
try {
System.out.print(prompt);
number = input.nextDouble();
more = false;
} catch(InputMismatchException e) {
System.out.println(
"Error -- enter digits only!");
input.nextLine(); // clear the buffer
} catch(NoSuchElementException e) {
System.out.println("\nGoodbye");
System.exit(0);
}
}
return number;
}
}
|
- Note that there is still a loop in the
readDouble() method -- can you see it?
- Programmers commonly develop a library of static input methods like these
^ top
9.1.7: Summary
- A common way to develop a program is to first make the code work assuming that nothing unusual happens
- After the usual case works, then you consider the exceptional cases
- Java provides exception handling to handle these exceptional cases
- Many exceptions can occur because of user input errors
- To catch and handle exceptions you use both
try and catch statements
try {
// One or more statements that can throw an exception
} catch(Exception e) {
// Exception handling code
// Can have many catch blocks
}
To allow users to correct their errors, you need to add a looping mechanism around the input statement
boolean more = true;
while (more) {
try {
System.out.print("Enter net cost: ");
cost = input.nextDouble();
// May have more statements
more = false;
} catch(InputMismatchException e) {
System.out.println(
"Error -- enter digits only!");
input.nextLine(); // clear the '\n'
} // may need more catch statements
}
Since input is a frequent occurrence, it is common to write user input methods
One example is readDouble():
public static double readDouble(Scanner input,
String prompt) {
double number = 0;
boolean more = true;
while (more) {
try {
System.out.print(prompt);
number = input.nextDouble();
more = false;
} catch(InputMismatchException e) {
System.out.println(
"Error -- only enter numbers!");
input.nextLine(); // clear the input
} catch(NoSuchElementException e) {
System.out.println("\nGoodbye");
System.exit(0);
}
}
return number;
}
Check Yourself
- What is an exception?
- What is an exception handler?
- What is a stack trace?
- What is the Java syntax for exception handling
- When is the code within a catch block executed?
^ top
Exercise 9.1
Take one minute to prepare an answer the following question.
- By number, which lines are executed by the following if the user enters "$100" for the cost?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import java.util.*;
public class TotalCalculator2 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double cost = 0, tax = 0;
try {
System.out.print("Enter cost: ");
cost = input.nextDouble();
System.out.print("Enter tax: ");
tax = input.nextDouble();
double total = cost + tax;
System.out.println("Total: " + total);
} catch(InputMismatchException e) {
System.out.println(
"Error -- enter digits only!");
} catch(NoSuchElementException e) { // Ctrl-C
System.out.println("\nGoodbye!");
System.exit(0);
}
System.out.println("Thanks for paying!");
}
}
|
^ top
9.2: More Exception Topics
Learner Outcomes
At the end of the lesson the student will be able to:
- Explain the difference between checked and unchecked exceptions
- Use the
throws clause when defining a method
- Throw an exception
- Use predefined
Exception classes
- Write a custom class that defines a new exception
|
^ top
9.2.1: Kinds of Exceptions
- Java has three categories of exceptional conditions:
- Errors
- Checked exceptions
- Unchecked exceptions
- These exceptions are organized in an inheritance hierarchy as shown below

- Exceptions with
RuntimeException as an ancestor are unchecked exceptions
Errors
- Errors are exceptional conditions that are external to the application
- Usually the application cannot recover from these types of errors
- For example, suppose that while your program is reading from a file that the computer has a hardware failure
- You may want to alert the user, but there is little that the program can do to recover
Checked Exceptions
- A checked exception is an exceptional condition that a program should be able to recover from
- Java forces these types of problems to be provided for if they occur
- The compiler checks that some mechanism is in place for receiving and processing the exception object
- Since it is checked by the compiler, it is known as a checked exception
- An example of this type of exception is the
FileNotFoundException
- Normally, your program reads a file using a name supplied by the user
- However, sometimes a user will supply a wrong name
- In these cases your program should notify the user and ask for the correct name
Unchecked (Runtime) Exceptions
^ top
9.2.2: What Exception Can Occur?
- The are two usual ways to determine what exceptions can occur in a program
- The first way is to try the code and see what happens
- If we tried to code our TotalCalculator program without a
try-catch:
Scanner input = new Scanner(System.in);
double cost = 0, tax = 0;
System.out.print("Enter cost: ");
cost = input.nextDouble();
System.out.print("Enter tax: ");
tax = input.nextDouble();
double total = cost + tax;
System.out.println("Total: " + total);
System.out.println("Thanks for paying!");
We found we could get a an exception like:
Enter cost: $100
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextDouble(Scanner.java:2387)
at TotalCalculator1.main(TotalCalculator1.java:9)
- This tells you that you need to code a
try-catch for an InputMismatchException
- Sometimes you might want to know what the possible exceptions might be in your code
- To find out, you can look up exceptions in the Java API
- For example, you can look up the documentation for the
Scanner method: nextDouble()
- You then examine the list of possible exceptions and determine if and how they might occur in your program
- Note that exceptions with
RuntimeException as an ancestor are unchecked
- Otherwise, they are checked exceptions
More Information
^ top
9.2.3: Using the throws Clause
- Anytime your program uses a method that can cause a checked exception, your program must do something with it
- If you decide the method cannot handle the exception, you use a
throws clause to send the exception to the caller
- The general syntax for throwing an exception:
[accessModifier] returnType methodName(parameterList)
throws ExceptionType1, ExceptionType2,... {
// statements
}
- Where:
- accessModifier: determines which classes can access this method
- returnType: the type of value returned by the method, or
void for no return value
- methodName: the name you make up for the method
- parameterList: the types and names of the parameters
- ExceptionTypeX: the type of exception a method throws
- For example:
public static void main(String[] args)
throws java.io.IOException {
- Throwing an exception is like passing the buck:
- Requires the calling method to deal with the exception
- The calling method can also throw the exception
- Eventually some method should catch it or the general exception handler is called
How Exceptions are Propagated
- When methods cannot handle an exception, that method should throw the exception
- The user of the method can then decide how to handle the exception
- Methods can call other methods that can throw an exception
- This chain continues usually until one method catches the exception

Example of Exception Propagation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class ExceptionPropogation {
public static void main(String[] args) {
methodD();
}
public static void methodD() {
try {
methodC();
} catch (Exception e) {
System.out.println("Caught exception");
}
}
public static void methodC() throws Exception {
methodB();
}
public static void methodB() throws Exception {
methodA();
}
public static void methodA() throws Exception {
throw new Exception();
}
}
|
^ top
9.2.4: Throwing Exceptions
throw new Exception("Exception message");
Typically, you decide to throw an exception after checking for an error condition
if (cost < 0) {
throw new Exception(
"Cost cannot be less than 0");
}
To demonstrate, let us throw an exception in an example program
Example Program Using throw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
import java.util.*;
public class TotalCalculator5 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double cost = 0, tax = 0;
boolean more = true;
while (more) {
try {
System.out.print("Enter cost: ");
cost = input.nextDouble();
if (cost < 0) {
throw new Exception(
"Cost cannot be less than 0");
}
System.out.print("Enter tax: ");
tax = input.nextDouble();
if (tax < 0) {
throw new Exception(
"Tax cannot be less than 0");
}
double total = cost + tax;
System.out.println("Total: " + total);
more = false;
} catch(Exception e) {
String message = e.getMessage();
System.out.println(message);
input.nextLine(); // clear the buffer
}
}
System.out.println("Thanks for paying!");
}
}
|
- Note the use the
getMessage() method to explain the error
- There are a few other commonly used exception methods shown in the table below
When to Throw an Exception
- Your program should only throw exceptions for exceptional conditions
- This may happen when a method encounters a situation where it cannot complete its task
- For example: the wrong file name was passed to the method opening a file
- Throw an exception to the calling method, which can ask the user for the correct name
Commonly Used Methods of the Throwable Class
| Method |
Description |
| getMessage() |
Returns the message associated with the exception, if available. |
| printStackTrace() |
Prints the stack trace to the standard error stream. |
| toString() |
Returns a string with the name of the exception class along with the message associated with the exception, if available. |
^ top
9.2.5: Predefined Exception Classes
- As we have seen, there are more exception classes than the single class
Exception
- Some of them are shown in the following tree
- You can also write your own exceptions, which we will cover in the following section
- However, you should use standard exceptions wherever possible
java.lang.Throwable
|
+--java.lang.Error (Unchecked)
|
+--java.lang.Exception (Checked)
|
+--java.lang.InterruptedException
|
+--java.io.IOException
|
+--java.lang.RuntimeException (Unchecked)
|
+--java.lang.ArithmeticException
|
+--java.lang.IllegalArgumentException
|
+--java.lang.IllegalStateException
|
+--java.lang.IndexOutOfBoundsException
|
+--java.lang.NullPointerException
|
+--java.lang.UnsupportedOperationException
|
+--java.util.InputMismatchException
^ top
9.2.6: Writing Custom Exception Classes
- You can define your own exception class
- There are two main reasons to write your own exception class:
- To carry the precise information you want thrown to the catch block
- To have a different type for every kind of exceptional case
- You must derived your exception from some already defined exception class
- Often all you need to code is the constructors
- You should always define two constructors for an exception class:
- A constructor taking no arguments that defines a default message string and calls the superclass constructor
- A constructor that takes a
String message argument and calls the superclass constructor
- Following is a "toy" example of a custom exception class
Custom Exception Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class DivisionByZeroException extends Exception {
/**
* Default constructor with a default error message.
*/
public DivisionByZeroException() {
super("Division by zero!");
}
/**
* Overloaded constructor for custom error message.
*
* @param message The custom error message.
*/
public DivisionByZeroException(String message) {
super(message);
}
}
|
Program Using the Custom Exception
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
import java.util.*;
public class Divide2Nums {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double numerator = 0, denominator = 0;
double quotient = 0;
boolean valid = false;
numerator = readDouble(input,
"Enter numerator: ");
while (!valid) {
try {
denominator = readDouble(input,
"Enter denominator: ");
if (denominator == 0) {
throw new DivisionByZeroException();
}
quotient = numerator / denominator;
valid = true;
} catch (DivisionByZeroException e) {
System.out.println(e.getMessage());
}
}
System.out.println(numerator + " / "
+ denominator + " = " + quotient);
}
/**
* Read a double from the console.
*
* @param input Scanner object to read from.
* @param prompt User prompt to show before input
* @return A double entered by the user.
*/
public static double readDouble(Scanner input,
String prompt) {
double number = 0;
try {
System.out.print(prompt);
number = input.nextDouble();
} catch(InputMismatchException e) {
System.out.println(
"Error -- enter digits only!");
input.nextLine(); // clear the '\n'
return readDouble(input, prompt);
} catch(NoSuchElementException e) {
System.out.println("\nGoodbye!");
System.exit(0);
}
return number;
}
}
|
^ top
9.2.7: Summary
- Java has three categories of exceptional conditions:
- Errors: external to the application
- Checked exceptions: recoverable condition that the compiler forces a program to handle
- Unchecked exceptions: compiler does NOT force a program to handle
- These exceptions are organized in an inheritance hierarchy as shown below

Exception is the ancestor of checked exceptions and RuntimeException is the ancestor of unchecked exceptions
- To determine what kind of exception can occur, you can:
- Try the code and see what happens
- Look up the exceptions in the Java API
- If a method cannot handle the exception, it should throw the exception to the calling method
- To throw an exception you add a throws clause in the method header
public static void main(String[] args)
throws java.io.IOException {
- To create an exception condition, you code a
throw statement:
throw new Exception("Exception message");
- Typically, you decide to throw an exception after checking for an error condition, like:
if (cost < 0) {
throw new Exception(
"Cost cannot be less than 0");
}
- When you catch an exception, you can use
getMessage() to display the error message associated with the exception
- When throwing an exception, you can use a predefine exception class or write a custom exception class
- You should use predefined exception class whenever you can
- However, there are two main reasons to write your own exception class:
- To carry the precise information you want thrown to the catch block
- To have a different type for every kind of exceptional case
- You must derived your exception from some already defined
Exception class
- When writing your own exception, you should always define two constructors:
- A constructor taking no arguments that defines a default message string and calls the superclass constructor
- A constructor that takes a
String message argument and calls the superclass constructor
- For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class DivisionByZeroException extends Exception {
/**
* Default constructor with a default error message.
*/
public DivisionByZeroException() {
super("Division by zero!");
}
/**
* Overloaded constructor for custom error message.
*
* @param message The custom error message.
*/
public DivisionByZeroException(String message) {
super(message);
}
}
|
^ top
Exercise 9.2
Take one minute to prepare answers to the following questions:
- What output is produced by the following code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public class WaitTime {
public static void main(String[] args) {
int waitTime = 50;
System.out.println("Before try-block");
try {
System.out.println("Entering try-block");
if (waitTime > 30) {
throw new Exception("Over 30");
} else if (waitTime < 30) {
throw new Exception("Under 30");
}
System.out.println("No exception");
System.out.println("Exiting try-block");
} catch(Exception e) {
System.err.println(e.getMessage());
}
System.out.println("After catch-block");
}
}
|
^ top
9.3: Streams and File I/O
Learner Outcomes
At the end of the lesson the student will be able to:
- List the types of files
- Create and use
File objects
- Get information about files from the native file system
- List directory contents
|
^ top
9.3.1: About Program I/O
- Program I/O = Program Input/Output
- Input to and output from programs
- Input can be from a keyboard, mouse or file
- Output can be to a display screen, printer or file
- Note that files can be both input and output devices for programs
- Advantages of file I/O:
- Data still exists after the program ends
- Input can be automated (rather than entered manually)
- Output from one program can be input to another
- To store and retrieve data in a file, we need two items:
- A file
- A file stream object
- We will look at files first
^ top
9.3.2: Files
File: a collection of data stored under a common name on a storage medium.
- Files provide long-term storage of large amounts of data
- Usually, you store files on non-volatile storage mediums
- Magnetic disks
- Optical disks
- Flash storage, like USB storage devices
- File are a single sequence of bytes
| Byte 0 |
Byte 1 |
Byte 2 |
... |
Byte n−1 |
End-of-file marker |
- The operating system keeps track of the number of bytes in a file
- Files must have a name
- Naming requirements depend on the underlying operating system (OS)
- The operating system organizes files into directories
^ top
9.3.3: Types of Files
- All data in a file is ultimately just zeros and ones
- It is up to the program using the file to understand the meaning and internal format of the data
- In general, programs interpret data using two broad categories: text and binary
Text Files
- In text files, the bits represent printable characters
- Files are usually stored as one byte per character (ASCII)
- Each line is delimited by end-of-line characters:
- Macintosh (before OS-X): "
\r"
- Unix: "
\n"
- Windows: "
\r\n"
- You can read text files because each byte is interpreted by a program as textual characters
- Some of these programs, like TextPad, then display the textual data to your computer's screen
- Since there are many programs that read and display text, text files are called human readable
Binary Files
- Data other than text is usually referred to as binary data
- Each bit represents some type of encoded information
- E.g.: program instructions or integer data
- Binary files are easily read by the computer but not by humans
- The following table compares binary and text values saved in a file
- First we consider the value "1234" as ASCII codes and compare these bits to a binary value of
1234
Comparing Binary and Textual Data
| Description |
Byte 0 |
Byte 1 |
Byte 2 |
Byte 3 |
"1234" as char's |
'1' |
'2' |
'3' |
'4' |
| "1234" as ASCII codes (bytes) |
49 |
50 |
51 |
52 |
| "1234" as ASCII codes (bits) |
00110001 |
00110010 |
00110011 |
00110100 |
(int) 1234 as binary bits |
00000000 |
00000000 |
00000100 |
11010010 |
^ top
9.3.4: Creating File Objects
- File class represents a file on the native file system
- You create a
File object referring to a file
- Then you can query the object for information about that file
Common Constructors for Class File
Examples of Creating Files Objects
- You can create a
File object in the current directory
File myFile = new File("myfile.txt");
Can create a File object using an absolute pathname
Specifies the entire path and file name for the file
File myFile = new File("C:/docs/myfile.txt");
You can use a relative pathname to specify a file
Refers to a file starting from the current directory
File myFile = new File("docs/myfile.txt");
You can use a Universal Naming Convention to refer to a file
Starts with two slashes (//) followed by a hostname and pathname
File myFile = new File("//server/path/myfile.txt");
You can use two strings to specify a file:
String pathname = "C:/docs";
String filename = "myfile.txt";
File myFile = new File(pathname, filename);
You can use a File object and a string to specify a file
File dir = new File("C:/docs");
File myFile = new File(dir, "myfile.txt");
Note that forward slashes work on both UNIX and Windows systems
Always use forward slashes to make your code more portable
^ top
9.3.5: Using File Objects
- We can use
File objects for many tasks
- For instance we can:
- Test some attributes of files or directories
- Get information about files
- Get lists of directory contents
- Create files and directories
- Delete files and directories
- You can see some of the commonly used methods listed below
Some Methods that Test a File
| Method |
Description |
| canRead() |
Returns true if the pathname exists and can be read by the program. |
| canWrite() |
Returns true if the pathname exists and a program can write to it. |
| exists() |
Returns true if the pathname exists. |
| isDirectory() |
Returns true if the pathname exists and refers to a directory. |
| isFile() |
Returns true if the pathname exists and refers to a file. |
Some Methods that Return Information about a File
| Method |
Description |
| getName() |
Returns the name of the file or directory as a String. |
| getPath() |
Returns the name of the file or directory as a String. |
| lastModified() |
Returns the time that the file was last modified as the number of milliseconds since January 1, 1970. |
| length() |
Returns the length of the file as a long type. |
Some Methods that work with Directories
| Method |
Description |
| list() |
If the object refers to a directory, returns an array of strings naming the files and directories. |
| listFiles() |
If the object refers to a directory, returns an array of File objects for the files and directories. |
| listRoots() |
A static method that returns an array of File objects representing the drives available to the current system. |
| mkdir() |
Creates the directory named by the File pathname. |
Other Methods that work with File Objects
| Method |
Description |
| createNewFile() |
Creates a new, empty file if a file with this name does not yet exist. |
| delete() |
Deletes the file or directory referred to by the File object. |
| setReadOnly() |
Makes the file read-only. If successful, returns true. |
^ top
9.3.6: Working with Files and Directories
- The following programs show some uses for the
File object
Getting Information About a File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
import java.io.*;
public class FileInfo {
public static void main(String[] args) throws IOException {
File myFile = new File("myfile.txt");
myFile.createNewFile();
if (myFile.exists()) {
System.out.println("Name: " + myFile.getName());
System.out.println("Path: " + myFile.getPath());
System.out.println("Writable: " + myFile.canWrite());
} else
System.out.println("The " + myFile.getName()
+ " file doesn't exist.");
}
}
|
Listing Directory Contents
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
import java.io.*;
public class DirList {
public static void main(String[] args)
throws IOException {
File dir = new File("./"); //current directory
if (dir.exists() && dir.isDirectory()) {
System.out.println("Dir: "
+ dir.getCanonicalPath());
String[] files = dir.list();
for (int i = 0; i < files.length; i++)
System.out.println(files[i]);
}
}
}
|
Working with I/O Exceptions
- Note the
throws IOException clause in the above examples
- File I/O requires you to work with I/O exceptions
- Your code will not compile unless you handle the exception
- Either using
try-catch or throws
- There are many types of I/O exceptions you can work with as shown below
- However,
IOException is the ancestor of all I/O exceptions
Common I/O Exceptions
^ top
9.3.7: Summary
- To identify a file you create a
File object
- You identify the file with either an absolute pathname or a relative pathname
- To identify a file on a remote computer, you use the Universal Naming Convention
- The
File class provides many methods that you can use to:
- Check whether a file or directory exists
- Get information about a file
- Create or delete files and directories
- Many methods of Java I/O classes throw I/O exceptions that you need to handle
Check Yourself
- What is the difference between a text file and a binary file?
- What is the purpose of the
File class?
- What is an absolute pathname?
- What is a relative pathname?
- What is an I/O exception?
- Why must you handle I/O exceptions?
- What can you do to handle I/O exceptions?
^ top
Exercise 9.3
Take one minute to prepare an answer to the Check Yourself questions. We will review the questions as time permits.
^ top
9.4: Text File I/O
Learner Outcomes
At the end of the lesson the student will be able to:
- Describe the purpose of a stream
- Work with I/O exceptions
- Write text to files
- Read text from files
|
^ top
9.4.1: Streams
Stream: a one-way transmission path that either delivers data to a destination (screen, file, etc.) or that takes data from a source (keyboard, file, etc.)
- A stream connects a program to an I/O object
- Input stream: an object that provides a sequence of bytes to a program

- Output stream: an object that accepts a sequence of bytes from a program

File Streams
File stream: a one-way transmission path used to connect a program to a file.
- File streams can be either input or output streams
- File input streams receive data from a file
- File output streams send data to a file
- Each file your program uses will need a separate file stream object
Basic File Streams
- Since there are two types of files, there are streams to support each type
- Use character streams to read and write text files:
- Use binary streams to read and write binary files:
^ top
9.4.2: Text Streams
- Streams are implemented using classes and objects
- To write and read text, you use character streams
- A character stream processes characters through the stream
- There is a separate set of classes for writing and reading character streams
- These classes are organized in an inheritance hierarchy as shown below
Some Classes from the Writer Hierarchy
Writer: Foundation class for writing character streams
|
+--BufferedWriter: Add a buffer to the stream
|
+--PrintWriter: Convert binary data to text
|
+--OutputStreamWriter: Bridge character to binary streams
|
+--FileWriter: Connects a stream to a file
Some Classes from the Reader Hierarchy
Reader: Foundation class for reading character streams
|
+--BufferedReader: Add a buffer to the stream
|
+--InputStreamReader: Bridge character to binary streams
|
+--FileReader: Connects a stream to a file
^ top
9.4.3: Layering Streams
- Usually, any one stream does have not all the functionality you want
- Instead, it is common to layer two or more streams
Writing to a Text Stream
Buffering
- Every time a byte or sequence of bytes is written or read to a file, the OS must perform a series of operations
- Buffering improves performance of I/O by reducing the number of calls to the OS
- A program copies each output to a block of memory called a buffer
- The entire buffer is output to disk at once
- One long disk access takes less time than many smaller ones

Adding a Buffered Layer
- You use buffered stream classes to improve I/O performance:
- We can add a buffering layer to our previous stream example:
FileWriter fw = new FileWriter("myfile.txt");
BufferedWriter buf = new BufferedWriter(fw);
PrintWriter out = new PrintWriter(buf);
- Another way to write the same functionality:
PrintWriter out = new PrintWriter(
new BufferedWriter(
new FileWriter("myfile.txt")));
^ top
9.4.4: Connecting a Character Output Stream to a File
- To write to a text file, you create a character output stream
- To do this, you need to layer two or more classes from the
Writer hierarchy
- An example of how to accomplish this task is shown below
Classes Connecting a Character Output Stream to a File
File data = new File("data.txt");
PrintWriter out = new PrintWriter(
new BufferedWriter(
new FileWriter(data)));
Mix and Match
^ top
9.4.5: Procedure for Writing a Text File
- Create a
File object with a pathname to your file:
File data = new File("data.txt");
- Connect the file to a stream with a
FileWriter:
FileWriter fw = new FileWriter(data);
If you want to append data then use:
FileWriter fw = new FileWriter(data, true);
- Add a buffer for the output with a
BufferedWriter:
BufferedWriter buf = new BufferedWriter(fw);
- Add methods to convert binary data to character data with a
PrintWriter:
PrintWriter out = new PrintWriter(buf);
- Write to the file using the
print() and println() methods:
out.println("This is a string");
out.println('c');
out.println(1234);
out.println(1.234);
for (int i = 0; i <= 10; i++) {
out.print(i + ",");
}
out.println();
- Close the streams when finished writing:
out.close();
Note that you can nest the constructor calls as shown in the example below
Example Program Writing a Text File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import java.io.*;
class TextWriterApp {
public static void main(String[] args)
throws IOException {
File data = new File("data.txt");
PrintWriter out = new PrintWriter(
new BufferedWriter(
new FileWriter(data)));
out.println("This is a string");
out.println('c');
out.println(1234);
out.println(1.234);
for (int i = 0; i <= 10; i++) {
out.print(i + " ");
}
out.println();
out.close();
System.out.println("Finished writing file");
}
}
|
^ top
9.4.6: Connecting a Character Input Stream to a File
- To read from a text file, you need to create a character input stream
- To do this, you need to layer two or more classes from the
Reader hierarchy
- Note that there is no "PrintReader" class
- Instead we can use the same
Scanner object we used for reading from the keyboard
- An example of how to accomplish this task is shown below
Classes Connecting a Character Output Stream to a File
File data = new File("data.txt");
Scanner in = new Scanner(
new BufferedReader(
new FileReader(data)));
Mix and Match
- There are many ways to connect a character input stream to a file
- You can "mix and match"
Reader classes to get the functionality you need
- This list of constructors should give you some idea how this is possible
- Recall that any class ending in the word "Reader" is a
Reader subclass
- In addition, all "reader" classes implement the
Readable interface
FileReader(File file)
FileReader(String pathname)
BufferedReader(Reader in)
Scanner(Readable source)
Some Commonly Used Methods of a Scanner Object
| Method |
Description |
next() |
Returns the next token as a String object. |
nextLine() |
Returns the rest of the current line as a String object. |
nextDouble() |
Provides classes to handle text, dates, and numbers |
nextInt() |
Returns the next token as an int value. |
^ top
9.4.7: Procedure For Reading a Text File
- Create a
File object with a pathname to your file.
File data = new File("data.txt");
- Connect the file to a stream with a
FileReader.
FileReader fr = new FileReader(data);
- Add a buffer for the input with a
BufferedReader.
BufferedReader bin = new BufferedReader(fr);
- Add a Scanner object to parse the data.
Scanner in = new Scanner(bin);
- Read data using methods calls for the correct type
int x = in.nextInt();
- Close the streams when finished reading.
in.close();
Note that you can nest the constructor calls as shown in the example below
Example Program Reading a Text File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
import java.io.*;
import java.util.Scanner;
class TextReaderApp {
public static void main(String[] args)
throws IOException {
File data = new File("data.txt");
Scanner in = new Scanner(
new BufferedReader(
new FileReader(data)));
String str = in.nextLine();
System.out.println(str);
char ch = in.nextLine().charAt(0);
System.out.println(ch);
int x = in.nextInt();
System.out.println(x);
double d = in.nextDouble();
System.out.println(d);
for (int i = 0; i <= 10; i++) {
x = in.nextInt();
System.out.print(x + " ");
}
System.out.println();
in.close();
}
}
|
^ top
9.4.8: Testing for End of File
- Sometimes you do not know how many lines are in a file
- To solve this, the typical approach is to use a loop to process the file
- The
Scanner object has methods like hasNext() to see if there is any more input in the stream
- You can use these methods to signal when your program reaches the end of a file
Example Program Testing for End-of-File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import java.io.*;
import java.util.Scanner;
class TextReaderApp2 {
public static void main(String[] args)
throws IOException {
File data = new File("TextReaderApp2.java");
Scanner in = new Scanner(
new BufferedReader(
new FileReader(data)));
while (in.hasNext()) {
String line = in.nextLine();
System.out.println(line);
}
in.close();
}
}
|
Some Test Methods of a Scanner Object
| Method |
Description |
hasNext() |
Returns true if this scanner has another token in its input. |
hasNextLine() |
Returns true if there is another line in the input of this scanner. |
hasNextDouble() |
Returns true if the next token can be interpreted as a double value. |
hasNextInt() |
Returns true if the next token can be interpreted as an int value. |
^ top
9.4.9: Summary
- Programs read and write to files using streams
- A stream is a one-way transmission path that either delivers data to a destination or that takes data from a source.
- To read and write files, you use input and output streams
- Buffers improve the performance of disc operations by reducing the number of device operations
- To create a stream object with the desired functionality, you layer streams
Writing a Text File
Reading a Text File
Check Yourself
- How are I/O operations handled in Java?
- What is an output stream?
- What is an input stream?
^ top
Exercise 9.4
Take one minute to prepare an answer to the following question:
- What does the following snippet of code do?
File data = new File("data.txt");
Scanner in = new Scanner(
new BufferedReader(
new FileReader(data)));
int count = 0;
while (in.hasNextLine()) {
String line = in.nextLine();
count++;
System.out.println(count + ": " + line);
}
in.close();
^ top
Wrap Up
^ top
Home
| Blackboard
| Announcements
| Schedule
| Room Policies
| Course Info
Help
| FAQ's
| HowTo's
| Links
Last Updated: April 05 2009 @21:53:20
|