Presentation is loading. Please wait.

Presentation is loading. Please wait.

Files Chapter 14 Copyright © 2000 W. W. Norton & Company.

Similar presentations


Presentation on theme: "Files Chapter 14 Copyright © 2000 W. W. Norton & Company."— Presentation transcript:

1 Files Chapter 14 Copyright © 2000 W. W. Norton & Company.
All rights reserved.

2 14.1 Files and Streams A file is a collection of related data that is given a name and placed on a storage medium. A file can be a place to keep data for a long period of time, or it can be used for temporary storage. Files can be stored on a variety of media, including hard drives, floppy disks, CD-ROMs, and tapes. Files can also be transmitted in various ways, such as over a computer network. All files are the same in one important respect: they consist of bytes. Copyright © 2000 W. W. Norton & Company. All rights reserved.

3 How Files Are Stored One way to see the sizes of files is to use the dir command in Windows: Volume in drive C has no label Volume Serial Number is 07CE-0C08 Directory of C:\programs\lottery <DIR> :02p . <DIR> :02p .. LOTTER~1 JAV :04p Lottery.java LOTTER~1 CLA :04p Lottery.class 2 file(s) bytes 2 dir(s) , MB free The Lottery.java file contains 283 bytes, and the Lottery.class file contains 511 bytes. Copyright © 2000 W. W. Norton & Company. All rights reserved.

4 How Files Are Stored In some files, each byte represents a character. In other files, the bytes mean other things. Suppose that a file consists of four bytes: Some possible meanings: The bytes represent the ASCII characters J, a, v, and a. The bytes represent a single integer. The first two bytes represent a short integer, and the second two represent another short integer. The bytes represent a single float value. Copyright © 2000 W. W. Norton & Company. All rights reserved.

5 How Files Are Stored Ways to leave hints about the contents of a file:
The file’s extension A “marker” in the file itself, usually at the beginning In Windows, an executable file begins with two special bytes containing the ASCII codes for the letters M and Z. In Unix, an executable file begins with a “magic number.” When the user tries to execute a program, Unix first checks for the magic number. Copyright © 2000 W. W. Norton & Company. All rights reserved.

6 Text Files Versus Binary Files
Files fall into two categories: In a text file, the bytes represent characters in some character set, such as ASCII or Unicode. In a binary file, the bytes don’t necessarily represent characters (although some of them may). Copyright © 2000 W. W. Norton & Company. All rights reserved.

7 Text Files Versus Binary Files
Text files have two characteristics that binary files don’t possess. First, text files are divided into lines. In Windows, the end-of-line marker is a carriage-return character ('\r') followed immediately by a line-feed character ('\n'). In Unix, the end-of-line marker is a single line-feed character. The Macintosh operating system uses a single carriage-return character. Copyright © 2000 W. W. Norton & Company. All rights reserved.

8 Text Files Versus Binary Files
Second, text files may contain a special “end-of-file” marker. In Windows, the marker is '\u1a' (Ctrl-Z). Ctrl-Z doesn’t have to be present, but if it is, it marks the end of the file. In a binary file, there’s no “end-of-line” or “end-of-file” marker; all bytes are treated equally. Copyright © 2000 W. W. Norton & Company. All rights reserved.

9 Text Files Versus Binary Files
Suppose that a Windows text file contains the following lines: Java rules! The bytes in the file, shown as hexadecimal codes: Copyright © 2000 W. W. Norton & Company. All rights reserved.

10 Streams Programs that work with files will need to use the java.io package. The names of many java.io classes include the word “stream.” A stream is an abstraction that represents any “file-like” source of input or destination for output. A stream object may be capable of reading from anything that resembles a file or writing to anything that resembles a file. Copyright © 2000 W. W. Norton & Company. All rights reserved.

11 Streams Classes whose names end with Stream are subclasses of InputStream and OutputStream: System.out and System.err are instances of the PrintStream class. Copyright © 2000 W. W. Norton & Company. All rights reserved.

12 Streams Other classes have names that end with Reader or Writer.
These classes are subclasses of Reader and Writer: Copyright © 2000 W. W. Norton & Company. All rights reserved.

13 Streams The reader and writer classes are designed to help with a common problem: Java stores characters in Unicode, whereas most software assumes that characters are stored in ASCII form. An instance of a Reader class solves the problem by automatically converting bytes to Unicode characters during input. Similarly, an instance of a Writer class will convert Unicode characters to single bytes during output. Copyright © 2000 W. W. Norton & Company. All rights reserved.

14 Stream Layering The first step in working with a file is creating an object that represents the file. Operations can then be performed on the file by calling instance methods. Many of the classes java.io are designed to be “layered,” with two or more objects involved. Calling a method that belongs to one object triggers a call to an “underlying” object, which may in turn call a method that belongs to a third object. Copyright © 2000 W. W. Norton & Company. All rights reserved.

15 Stream Layering For example, to write characters to a file, an instance of the FileWriter class will be needed. This class isn’t very efficient by itself, so a BufferedWriter object will need to be layered on top of the FileWriter object. The methods in the BufferedWriter class aren’t very convenient to use, however, so a PrintWriter object will need to be layered on top of the BufferedWriter object. Copyright © 2000 W. W. Norton & Company. All rights reserved.

16 Stream Layering A diagram showing the layering of the three classes:
Copyright © 2000 W. W. Norton & Company. All rights reserved.

17 Stream Layering Calling a method that belongs to PrintWriter in turn calls a method (or methods) belonging to BufferedWriter, which then calls a method(s) belonging to FileWriter. Layering provides flexibility: the programmer can combine classes in many different ways to get the right blend of efficiency and convenience. Copyright © 2000 W. W. Norton & Company. All rights reserved.

18 Working with Files Working with a file involves three steps:
Open the file Perform operations on the file Close the file Copyright © 2000 W. W. Norton & Company. All rights reserved.

19 Opening a File Opening a file requires specifying the file’s name and possibly its location. Opening a file is done by creating an instance of an appropriate stream class (or—in the case of a text file—a reader or writer class). This object represents the file within the program. Creating a FileOutputStream object opens a binary file for writing: FileOutputStream out = new FileOutputStream(filename); Copyright © 2000 W. W. Norton & Company. All rights reserved.

20 Opening a File Opening a file for input will fail—causing an exception to be thrown—unless the file already exists. When an existing file is opened for output, the file is normally truncated—the bytes already in the file are lost. Attempting to open a nonexistent file for output will cause the file to be created. Either way, the file is empty to begin with. Copyright © 2000 W. W. Norton & Company. All rights reserved.

21 Performing Operations on a File
File operations, such as reading data or writing data, are performed by calling instance methods that belong to the stream object’s class. The operations that can be performed on the out object are dictated by the methods in FileOutputStream (and its superclasses). One of these methods, named write, is capable of writing a single byte: out.write(b); // Writes the byte b Copyright © 2000 W. W. Norton & Company. All rights reserved.

22 Closing a File A file should be closed when no more operations will be performed on it. Closing a file is done by calling the close method: out.close(); All stream, reader, and writer classes support the close method (either by providing it or inheriting it). Copyright © 2000 W. W. Norton & Company. All rights reserved.

23 Obtaining File Names Ways to supply a file name to a program:
Build the name into the program Prompt the user to enter the name Obtain the name from the command line An example of obtaining file names from the command line: java CopyFile file1 file2 args[0] will contain the name of the file to be copied. args[1] will contain the name of the file that will store the copy. Copyright © 2000 W. W. Norton & Company. All rights reserved.

24 Buffering and Flushing
A buffer is a place where data is stored temporarily, usually on its way from one place to another. Buffers are common when working with files. When a program calls a method that writes to a file, the data being written usually goes into a buffer first. When the buffer is full, all the data in the buffer is then transferred to the file, and the buffer becomes empty. Copyright © 2000 W. W. Norton & Company. All rights reserved.

25 Buffering and Flushing
Similar actions take place when data is read from a file: a large chunk of data is first transferred to a buffer. The program then obtains small portions of the data from the buffer. When the buffer becomes empty, another large chunk is read from the file. Copyright © 2000 W. W. Norton & Company. All rights reserved.

26 Buffering and Flushing
Using buffers for input and output can dramatically improve a program’s performance. Transferring information to or from a disk drive is a relatively slow operation. Reading a byte from a buffer or storing a byte into a buffer takes hardly any time at all. It takes time to transfer the buffer contents to or from disk, but one large data transfer is much faster than many small ones. Copyright © 2000 W. W. Norton & Company. All rights reserved.

27 Buffering and Flushing
Java’s stream classes are designed to perform buffering without any action on the programmer’s part. Occasionally, though, it’s necessary to take a more active role. Normally, data written to a file goes into a buffer first. The buffer is flushed (written to the file) automatically when it’s full or the file is closed. Copyright © 2000 W. W. Norton & Company. All rights reserved.

28 Buffering and Flushing
The buffer can be flushed manually by calling the flush method: out.flush(); out can be an output stream or writer object Calling flush ensures that data is written to a file as soon as possible, where it will be safe. All output stream and writer classes support the flush method. Copyright © 2000 W. W. Norton & Company. All rights reserved.

29 File Pointers For each open file, Java maintains a file pointer, which keeps track of which byte will be the next to be read or written. If a file is opened for reading, the file pointer will be at the beginning: Copyright © 2000 W. W. Norton & Company. All rights reserved.

30 File Pointers If one byte is now read from the file, the file pointer will advance automatically to the next byte: The file pointer will eventually advance past the last byte in the file—a condition known as end of file. It’s important to test for this condition each time input is read from a file. Copyright © 2000 W. W. Norton & Company. All rights reserved.

31 File Pointers Writing to a file is similar: Java keeps track of the current position in the file and advances the file pointer after each write operation. Normally, writing starts at the beginning of a file. In some cases, however, it may be necessary to append data to the end of the file, thereby preserving the file’s original contents. Copyright © 2000 W. W. Norton & Company. All rights reserved.

32 File Pointers Reading or writing a file from beginning to end is called sequential access. Java also supports a different type of access, known as random access. Random access allows a program to move freely within a file. Random access requires the use of the RandomAccessFile class. Copyright © 2000 W. W. Norton & Company. All rights reserved.

33 14.2 The File Class File is one of the most fundamental classes in the java.io package. A File object represents a file stored on disk or some other medium. The File class allows a program to work with the properties of a file, not the contents of the file. File also provides a few basic file operations, including deleting a file and renaming a file. Copyright © 2000 W. W. Norton & Company. All rights reserved.

34 Creating File Objects There are several ways to create a File object.
One File constructor expects a string containing the file’s name: File f = new File("Lottery.java"); Java will try to locate the file in the current directory. To work with a file in a different directory, path information will need to be included in the string: File f = new File("c:\\programs\\lottery\\Lottery.java"); Copyright © 2000 W. W. Norton & Company. All rights reserved.

35 Creating File Objects The path and the file name can be supplied as separate arguments: File f = new File("c:\\programs\\lottery", "Lottery.java"); In Windows, two backslash characters are needed to separate directory names. Java would interpret a single backslash character as the beginning of an escape sequence. Copyright © 2000 W. W. Norton & Company. All rights reserved.

36 Creating File Objects Another way to solve the backslash problem is to use a slash character instead of a backslash to separate directory names: File f = new File("c:/programs/lottery/Lottery.java"); Although the backslash is the normal character for separating directory names in Windows, ordinary slashes will also work within Java programs. Copyright © 2000 W. W. Norton & Company. All rights reserved.

37 File Properties The File class provides a set of “query” methods that return information about a file: Description Action boolean canRead() Returns true if the program can read from this file. boolean canWrite() Returns true if the program can write to this file. boolean exists() Returns true if this file exists. boolean isDirectory() Returns true if this file is a directory. boolean isFile() Returns true if this file is normal (not a directory). long length() Returns the length of this file in bytes. String[] list() Returns an array of strings containing the names of the files in this directory. Copyright © 2000 W. W. Norton & Company. All rights reserved.

38 Program: Determining the Properties of a File
The FileProperties program prompts the user for the name of a file and then displays the file’s properties. Output of the program when asked to show the properties of the Lottery.java file: Enter a file name: Lottery.java File can be read File can be written File exists File is normal Length of file: 283 Copyright © 2000 W. W. Norton & Company. All rights reserved.

39 Program Behavior Output when asked to show the properties of the directory containing Lottery.java: Enter a file name: c:\programs\lottery File can be read File can be written File exists File is a directory Length of file: 0 Copyright © 2000 W. W. Norton & Company. All rights reserved.

40 FileProperties.java // Displays the properties of a file
import java.io.*; import jpb.*; public class FileProperties { public static void main(String[] args) { // Prompt user to enter file name SimpleIO.prompt("Enter a file name: "); String fileName = SimpleIO.readLine(); // Create a File object File f = new File(fileName); Copyright © 2000 W. W. Norton & Company. All rights reserved.

41 // Display properties of file if (f.canRead())
System.out.println("File can be read"); if (f.canWrite()) System.out.println("File can be written"); if (f.exists()) System.out.println("File exists"); if (f.isDirectory()) System.out.println("File is a directory"); if (f.isFile()) System.out.println("File is normal"); System.out.println("Length of file: " + f.length()); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

42 Program: Listing the Files in a Directory
The list method returns an array containing the names of all files in a particular directory. The ListFiles program uses list to display the names of the files in the current directory (represented by the file name "."). Output of the program when used to list the files in the c:\programs\lottery directory: Lottery.java Lottery.class Copyright © 2000 W. W. Norton & Company. All rights reserved.

43 ListFiles.java // Displays a list of all files in the current directory import java.io.*; public class ListFiles { public static void main(String[] args) { // Obtain a list of all files in the current directory File currentDirectory = new File("."); String[] fileNames = currentDirectory.list(); // Display each name in the list for (int i = 0; i < fileNames.length; i++) System.out.println(fileNames[i]); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

44 File Operations In addition to query methods, the File class also provides a few basic operations on files: Description Action boolean delete() Deletes this file. boolean mkdir() Creates a directory corresponding to this File object. boolean renameTo(File dest) Renames this file to the name specified by dest. All three methods return true if they are successful and false if they are not successful. Copyright © 2000 W. W. Norton & Company. All rights reserved.

45 Program: Renaming the Files in a Directory
The RenameFiles program displays the names of all files in the current directory, one by one, and allows the user to change the names of selected files. A sample session with the program: Rename Lottery.java (y/n)? n Rename Lottery.class (y/n)? y Enter new name: Lottery2.class Copyright © 2000 W. W. Norton & Company. All rights reserved.

46 RenameFiles.java // Renames selected files in the current directory
import java.io.*; import jpb.*; public class RenameFiles { public static void main(String[] args) { // Obtain a list of all files in the current directory File currentDirectory = new File("."); String[] fileNames = currentDirectory.list(); // Process each name in the list for (int i = 0; i < fileNames.length; i++) { // Ask user whether or not to rename file SimpleIO.prompt("Rename " + fileNames[i] + " (y/n)? "); String response = SimpleIO.readLine(); Copyright © 2000 W. W. Norton & Company. All rights reserved.

47 // If the answer is "y" or "Y", ask for new name and
// then call renameTo if (response.equalsIgnoreCase("y")) { SimpleIO.prompt("Enter new name: "); String newName = SimpleIO.readLine(); File oldFile = new File(fileNames[i]); File newFile = new File(newName); boolean successful = oldFile.renameTo(newFile); if (!successful) System.out.println("Could not rename " + fileNames[i] + " to " + newName); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

48 14.3 Reading and Writing Bytes
The FileInputStream and FileOutputStream classes are used to read and write single bytes or blocks of bytes. These classes are useful for writing file utilities, such as a program that makes a copy of a file. Copyright © 2000 W. W. Norton & Company. All rights reserved.

49 Writing Bytes Opening a file for writing is done by creating a FileOutputStream object. Common FileOutputStream constructors: Description Action FileOutputStream( Creates a FileOutputStream object String name) representing the file with the specified name. String name, representing the file with the specified name. boolean append) If append is true, bytes will be written to the end of the file rather than the beginning. File file) representing the specified File object. Copyright © 2000 W. W. Norton & Company. All rights reserved.

50 Writing Bytes The first constructor needs a file name (possibly containing path information) as its argument: FileOutputStream out = new FileOutputStream(fileName); The second constructor is used to specify that any bytes written to the file should be appended to the file, thereby preserving the file’s original contents. The third constructor takes a File object instead of a file name. Copyright © 2000 W. W. Norton & Company. All rights reserved.

51 Writing Bytes Using the FileOutputStream constructor to open an existing file causes the file to be truncated. The contents of the file is preserved, however, if the second constructor is used and the value of append is true. If the FileOutputStream constructor is given the name of a file that doesn’t exist, the file will be created. Copyright © 2000 W. W. Norton & Company. All rights reserved.

52 Writing Bytes If a file can’t be opened for writing, the FileOutputStream constructor will throw IOException. Because IOException is a checked exception, the constructor call will need to be enclosed within a try block. Starting with version 1.2 of the JDK, the FileOutputStream constructor throws FileNotFoundException instead of IOException. Copyright © 2000 W. W. Norton & Company. All rights reserved.

53 Writing Bytes The primary methods provided by FileOutputStream are all named write. These methods throw IOException if an error occurs. The first version of write writes a single byte: byte outputByte; out.write(outputByte); The second version writes a block of bytes stored in an array: byte[] buffer = new byte[512]; out.write(buffer); Copyright © 2000 W. W. Norton & Company. All rights reserved.

54 Writing Bytes The third version is also designed to write a block of bytes. It requires two additional arguments: byte[] buffer = new byte[512]; int count; out.write(buffer, 0, count); The second argument is an offset into the array; the value 0 indicates that the byte at position 0 will be the first to be written. The third argument is the number of bytes to write. Copyright © 2000 W. W. Norton & Company. All rights reserved.

55 Writing Bytes Most operations on a FileOutputStream object can throw IOException. An attempt to open a file for writing might fail because of an invalid path, no permission to write to the file, and so on. Attempts to write to the file could fail because the physical device has a problem or because the device is full. Copyright © 2000 W. W. Norton & Company. All rights reserved.

56 Writing Bytes A program that works with files should specify what action should be taken for each potential failure. Because IOException is a checked exception, possible errors can’t simply be ignored. In many cases, the program won’t be able to continue execution, but it should at least display a meaningful error message. In particular, it’s a good idea to display the name of the file that has caused the problem. Copyright © 2000 W. W. Norton & Company. All rights reserved.

57 Reading Bytes Reading bytes from a file requires the creation of a FileInputStream object. Common FileInputStream constructors: Description Action FileInputStream( Creates a FileInputStream object String name) representing the file with the specified name. File file) representing the specified File object. The first constructor requires a file name: FileInputStream in = new FileInputStream(fileName); Both constructors throw FileNotFoundException if the specified file can’t be opened for input. Copyright © 2000 W. W. Norton & Company. All rights reserved.

58 Reading Bytes The primary methods provided by FileInputStream are all named read: Description Action int read() Reads a byte, returning it in int form. int read(byte[] b) Reads bytes into b until the array is full or the end of the file has been reached. Returns the number of bytes read. int read(byte[] b, Reads up to len bytes into the array b, int off, starting at the position indicated by off. int len) Returns the number of bytes read. All three methods throw IOException if an error occurs. If any read method fails to read any input because it has reached the end of the file, it returns –1. Copyright © 2000 W. W. Norton & Company. All rights reserved.

59 Reading Bytes The first version of the read method reads a single byte: int byteValue = in.read(); read returns an int value, not a byte value, so the return value should be stored in an int variable. The variable should then be tested to see if it is equal to –1 (indicating that no byte could be read). If the variable is not equal to –1, its value can then be cast to byte form. Copyright © 2000 W. W. Norton & Company. All rights reserved.

60 Reading Bytes A loop that reads all the bytes in a file:
while (true) { int byteValue = in.read(); if (byteValue == -1) break; // End of file reached byte inputByte = (byte) byteValue; } In some cases, it’s possible to omit the cast and just leave the byte in the original int variable. Copyright © 2000 W. W. Norton & Company. All rights reserved.

61 Reading Bytes The second version of read reads bytes into an array until it’s full or no more bytes can be read: byte[] buffer = new byte[512]; int count = in.read(buffer); The third version specifies where the bytes should be stored in the array and how many bytes can be read. After calling either version of read, it’s important to test whether count has the value –1. If so, no bytes could be read because the method encountered the end of the file. Copyright © 2000 W. W. Norton & Company. All rights reserved.

62 Program: Copying a File
The CopyFile program will copy a file. The FileInputStream and FileOutputStream classes are perfect for this kind of program, which has no knowledge of what the original file contains. The user will supply the names of the original file and the new file on the command line: java CopyFile source destination source is the name of the original file, and destination is the name of the new file. Copyright © 2000 W. W. Norton & Company. All rights reserved.

63 Design of the CopyFile Program
Strategy: Check that there are two command-line arguments. Create a FileInputStream object to represent the source file. Create a FileOutputStream object to represent the destination file. Use a loop to read a block of bytes from the FileInputStream object and write the block to the FileOutputStream object. Close both files. Copyright © 2000 W. W. Norton & Company. All rights reserved.

64 Exceptions in the CopyFile Program
Checked exceptions that can occur: The FileInputStream constructor can throw FileNotFoundException. The FileOutputStream constructor can throw IOException (or FileNotFoundException). The read method in FileInputStream can throw IOException. The write method in FileOutputStream can throw IOException. The close methods in FileInputStream and FileOutputStream can throw IOException. Copyright © 2000 W. W. Norton & Company. All rights reserved.

65 Exceptions in the CopyFile Program
Instead of having a separate try block and catch block for each exception, most of the program will be enclosed within a single try block. After the try block will come two catch blocks, one for FileNotFoundException and one for IOException. Copyright © 2000 W. W. Norton & Company. All rights reserved.

66 CopyFile.java // Copies one file into another. The names of both files must // be specified on the command line. import java.io.*; public class CopyFile { public static void main(String[] args) { // Terminate program if number of command-line arguments // is wrong if (args.length != 2) { System.out.println("Usage: java CopyFile source dest"); System.exit(-1); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

67 // Open source file for input and destination file for // output
try { // Open source file for input and destination file for // output FileInputStream source = new FileInputStream(args[0]); FileOutputStream dest = new FileOutputStream(args[1]); // Set up a 512-byte buffer byte[] buffer = new byte[512]; // Copy bytes from the source file to the destination // file, 512 bytes at a time while (true) { int count = source.read(buffer); if (count == -1) break; dest.write(buffer, 0, count); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

68 // Close source and destination files source.close(); dest.close();
} catch (FileNotFoundException e) { System.out.println("File cannot be opened"); } catch (IOException e) { System.out.println("I/O error during copy"); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

69 14.4 Advanced Exception-Handling
The constructors and methods of the stream classes throw a variety of checked exceptions. Section 8.1 covered the rudiments of exception-handling, but a more detailed knowledge is needed in order to write programs that use files. Copyright © 2000 W. W. Norton & Company. All rights reserved.

70 The Hierarchy of Exception Classes
For each kind of exception, the Java API provides a corresponding class, such as IOException. A class named Throwable is the superclass (directly or indirectly) for all exception classes. The Throwable class has only two direct subclasses: Error and Exception. Classes that represent specific kinds of exceptions are subclasses of either Error or Exception. Copyright © 2000 W. W. Norton & Company. All rights reserved.

71 The Hierarchy of Exception Classes
A diagram showing how the exception classes are descended from Throwable: This diagram shows only a few of Throwable’s many subclasses. Copyright © 2000 W. W. Norton & Company. All rights reserved.

72 The Hierarchy of Exception Classes
Exception classes that extend Error represent unrecoverable errors, such as the Java interpreter failing to load a class or running out of memory. Classes that extend Exception represent problems that can potentially be handled within a program. Subclasses of Error or RuntimeException represent unchecked exceptions. Subclasses of Exception (but not RuntimeException) represent checked exceptions. Copyright © 2000 W. W. Norton & Company. All rights reserved.

73 Using Multiple catch Blocks
The fact that exception classes are related to each other has some interesting consequences for writing catch blocks. Suppose that a try block is followed by two or more catch blocks: try block catch (exception-type identifier) Copyright © 2000 W. W. Norton & Company. All rights reserved.

74 Using Multiple catch Blocks
If an exception is thrown inside a try block, the first catch block with a compatible exception type will be allowed to handle the exception. A catch block can catch exceptions of a specified type, as well as exceptions that belong to a subclass of that type. For example, a catch block for IOException can also catch FileNotFoundException, which is a subclass of IOException. Copyright © 2000 W. W. Norton & Company. All rights reserved.

75 Using Multiple catch Blocks
More than one catch block may be capable of handling a given exception: try { } catch (FileNotFoundException e) { } catch (IOException e) { } If a FileNotFoundException occurs, both catch blocks can potentially handle the exception, but only the first will be allowed to. Copyright © 2000 W. W. Norton & Company. All rights reserved.

76 Using Multiple catch Blocks
If catch blocks are put in the wrong order, it’s possible that an early catch block may end up catching exceptions that were meant for a later catch block: try { } catch (IOException e) { … // Catches FileNotFoundException as well } catch (FileNotFoundException e) { … // Never executed! } The second catch block can never be executed; if a FileNotFoundException occurs in the try block, the first catch block will handle the exception. Copyright © 2000 W. W. Norton & Company. All rights reserved.

77 Using Multiple catch Blocks
A catch block for IOException will catch all exceptions that belong to subclasses of IOException. Using such a catch block isn’t always appropriate, because the program can no longer act differently based on the particular exception. If a single catch block is used to catch I/O exceptions, it’s a good idea to have it display the message stored inside the IOException object. Copyright © 2000 W. W. Norton & Company. All rights reserved.

78 Using Multiple catch Blocks
It’s possible to write catch blocks that handle a wide variety of exceptions, not just I/O exceptions. A catch block for Exception will catch any exception that represents a recoverable error: try { } catch (IOException e) { … // Catches all I/O exceptions } catch (Exception e) { … // Catches all other exceptions } Copyright © 2000 W. W. Norton & Company. All rights reserved.

79 Using Multiple catch Blocks
Using Exception in a catch block can be dangerous, however: the block may catch exceptions that weren’t anticipated when the program was designed. Whenever possible, use specific exception classes in catch blocks, rather than broader classes such as Exception. Copyright © 2000 W. W. Norton & Company. All rights reserved.

80 finally Blocks After the last in a series of catch blocks, a finally block may be present: try block catch (exception-type identifier) finally Copyright © 2000 W. W. Norton & Company. All rights reserved.

81 finally Blocks The finally block is executed after the try block terminates or the exception is caught by a catch block. It must be executed even if the try block terminates prematurely because of a control statement (break, continue, or return). Typically, the finally block contains code that closes files or performs other “cleanup” actions. finally can even be used without any catch blocks. Copyright © 2000 W. W. Norton & Company. All rights reserved.

82 The throws Clause Actually, it’s not always the case that checked exceptions must be caught. When there’s a possibility that a checked exception might be thrown inside a method, there are two choices: Handle the exception within the method. Declare that the method throws the exception. Any method that calls this one will now be responsible for handling the exception. Copyright © 2000 W. W. Norton & Company. All rights reserved.

83 The throws Clause Consider the problem of writing a helper method that calls Java’s Thread.sleep method. Thread.sleep throws a checked exception named InterruptedException. One approach is to handle the exception within the new method: static void sleep(int time) { try { Thread.sleep(time); } catch (InterruptedException e) {} } Copyright © 2000 W. W. Norton & Company. All rights reserved.

84 The throws Clause The other possibility is to declare that the new method throws InterruptedException: static void sleep(int time) throws InterruptedException { Thread.sleep(time); } If InterruptedException occurs, the new method will return. The method that called it will now be responsible for catching the exception. Of course, that method might also have a throws clause. Copyright © 2000 W. W. Norton & Company. All rights reserved.

85 The throws Clause If a method fails to either catch a checked exception or declare it using throws, the compiler will issue an error message. Which technique is best depends on whether or not it is meaningful to deal with the exception inside the method where it’s thrown. If so, then there’s no reason for the calling method to know about the exception. Otherwise, it’s better to let the calling method handle the exception. Copyright © 2000 W. W. Norton & Company. All rights reserved.

86 Program: Copying a File (Revisited)
The throws clause is sometimes used by programmers looking for a shortcut. The CopyFile2 program is similar to the earlier CopyFile program, except that it does not handle exceptions. Instead, CopyFile2 declares that main throws IOException. There’s no need to mention that main throws FileNotFoundException, because FileNotFoundException is a subclass of IOException. Copyright © 2000 W. W. Norton & Company. All rights reserved.

87 Program Behavior If an IOException (or FileNotFound-Exception) occurs during the execution of CopyFile2, it will terminate with an error message about an unhandled exception. From a design standpoint, it’s better to handle the exception within the program itself, displaying an appropriate error message and, if possible, taking steps to recover from the exception. Copyright © 2000 W. W. Norton & Company. All rights reserved.

88 CopyFile2.java // Copies one file into another. The names of both files must // be specified on the command line. import java.io.*; public class CopyFile2 { public static void main(String[] args) throws IOException { // Terminate program if number of command-line arguments // is wrong if (args.length != 2) { System.out.println("Usage: java CopyFile2 source dest"); System.exit(-1); } // Open source file for input and destination file for // output FileInputStream source = new FileInputStream(args[0]); FileOutputStream dest = new FileOutputStream(args[1]); Copyright © 2000 W. W. Norton & Company. All rights reserved.

89 byte[] buffer = new byte[512];
// Set up a 512-byte buffer byte[] buffer = new byte[512]; // Copy bytes from the source file to the destination // file, 512 bytes at a time while (true) { int count = source.read(buffer); if (count == -1) break; dest.write(buffer, 0, count); } // Close source and destination files source.close(); dest.close(); Copyright © 2000 W. W. Norton & Company. All rights reserved.

90 14.5 Reading and Writing Data Types
The FileInputStream and FileOutput-Stream classes are not very convenient for reading and writing bytes that represent specific types of data. The DataInputStream and DataOutput-Stream classes are better suited for this task. These classes are designed for use with binary files. Numbers and other types of data can be written to a text file, but only after being converted to character form. Copyright © 2000 W. W. Norton & Company. All rights reserved.

91 Writing Data Types A DataOutputStream object can’t be created directly from a file name. Instead, a FileOutputStream object is first created, and then that object is used to create a DataOutputStream object: FileOutputStream fileOut = new FileOutputStream(fileName); DataOutputStream out = new DataOutputStream(fileOut); The DataOutputStream constructor will accept any output stream object as its argument. Copyright © 2000 W. W. Norton & Company. All rights reserved.

92 Writing Data Types To shorten the code, some programmers nest the FileOutputStream constructor inside the DataOutputStream constructor: DataOutputStream out = new DataOutputStream( new FileOutputStream(fileName)); Operations performed on the DataOutput-Stream object will indirectly affect the underlying FileOutputStream object. The methods in the DataOutputStream class are capable of writing data of specific types. Copyright © 2000 W. W. Norton & Company. All rights reserved.

93 Writing Data Types A partial list of DataOutputStream methods:
Description Action void write(int b) Writes the value of b as a single byte. void write(byte[] b, Writes len bytes of the array b, start- int off, int len) ing at the position indicated by off. void writeBoolean( Writes the value of v as a byte contain- boolean v) ing either 1 (true) or 0 (false). void writeByte(int v) Writes the value of v as a single byte. void writeChar(int v) Writes the value of v as 2 bytes. void writeDouble(double v) Writes the value of v as 8 bytes. void writeFloat(float v) Writes the value of v as 4 bytes. void writeInt(int v) Writes the value of v as 4 bytes. void writeLong(long v) Writes the value of v as 8 bytes. void writeShort(int v) Writes the value of v as 2 bytes. Copyright © 2000 W. W. Norton & Company. All rights reserved.

94 Writing Data Types All of these methods throw IOException if an error occurs. An example of using writeInt to write the value of an int variable: out.writeInt(n); Four bytes (the value of n in binary) will be written to the stream. The other DataOutputStream methods are called in a similar fashion. Copyright © 2000 W. W. Norton & Company. All rights reserved.

95 Writing Strings Writing strings to a DataOutputStream is a bit tricky, because a string doesn’t have a fixed size. DataOutputStream has three different methods for writing strings: writeBytes, writeChars, and writeUTF. All three methods throw IOException if an error occurs. Copyright © 2000 W. W. Norton & Company. All rights reserved.

96 Writing Strings The writeBytes method writes a string as a series of single bytes. The following call writes three bytes: out.writeBytes("abc"); The writeChars method writes a string as a series of Unicode characters, each of which requires two bytes. The following call writes six bytes: out.writeChars("abc"); Copyright © 2000 W. W. Norton & Company. All rights reserved.

97 Writing Strings Reading a string that’s been written by either writeBytes or writeChars could be difficult, because there’s no indication in the file itself of how many characters are in the string. The writeUTF method avoids this problem. This method uses an encoding scheme known as UTF-8 to write a string in such a way that it can be read later. Copyright © 2000 W. W. Norton & Company. All rights reserved.

98 Writing Strings The UTF-8 encoding of a string containing ASCII characters consists of a two-byte integer (the length of the string), followed by the characters in the string, each as a single byte. Example calls of writeUTF: out.writeUTF("so"); out.writeUTF("far"); These calls write a total of nine bytes: Copyright © 2000 W. W. Norton & Company. All rights reserved.

99 Writing Strings In UTF, non-ASCII characters (plus the null character) are stored using two or three bytes. The two bytes that are written ahead of the string represent the number of bytes in the string’s encoding, not the original length of the string. The advantage of the writeUTF method is that each string is preceded by its size, making it easy to recover the original string when the file is read. The readUTF method (in the DataInputStream class) is designed to read strings written in UTF form. Copyright © 2000 W. W. Norton & Company. All rights reserved.

100 Reading Data Types In order to read data that was written to a DataOutputStream, a DataInputStream object is needed. A DataInputStream object is normally layered on top of a FileInputStream object: FileInputStream fileIn = new FileInputStream(fileName); DataInputStream in = new DataInputStream(fileIn); The parameter for the DataInputStream constructor has type InputStream. Copyright © 2000 W. W. Norton & Company. All rights reserved.

101 Reading Data Types A partial list of DataInputStream methods:
Description Action int read(byte[] b) Reads bytes into b until the array is full or the end of the file has been reached. Returns the number of bytes read. int read(byte[] b, Reads up to len bytes of data into int off, the array b, starting at the position int len) indicated by off. Returns the number of bytes read. boolean readBoolean() Reads a single byte. Returns false if the byte is 0; returns true otherwise. (continued) Copyright © 2000 W. W. Norton & Company. All rights reserved.

102 Reading Data Types Description Action byte readByte() Reads a single byte and returns it. char readChar() Reads a 2-byte char value and returns it. double readDouble() Reads an 8-byte double value and returns it. float readFloat() Reads a 4-byte float value and returns it. int readInt() Reads a 4-byte int value and returns it. long readLong() Reads an 8-byte long value and returns it. short readShort() Reads a 2-byte short value and returns it. String readUTF() Reads a string and returns it. The string is assumed to be stored using UTF-8 encoding. All these methods throw IOException if an error occurs. Copyright © 2000 W. W. Norton & Company. All rights reserved.

103 Reading Data Types If one of the read methods fails to read any input because it reaches the end of the file, it returns –1. Each of the other methods throws EOFException if it fails to read the necessary number of bytes because reaches the end of the file. An example of using readInt to read an int value: int n = in.readInt(); Copyright © 2000 W. W. Norton & Company. All rights reserved.

104 14.6 Reading and Writing Characters
To read and write text files—files that contain character data—the preferred technique is to use reader and writer classes. Reader objects are capable of translating single bytes into the two-byte Unicode characters that Java uses. Writer objects perform the opposite translation, converting Unicode characters to single bytes. Copyright © 2000 W. W. Norton & Company. All rights reserved.

105 Writing to a Text File The FileWriter class is similar to the FileOutputStream class, except that it’s designed for use with text files. As it writes characters to a file, a FileWriter object will automatically convert each Unicode character into a single byte. Copyright © 2000 W. W. Norton & Company. All rights reserved.

106 Writing to a Text File Constructors for the FileWriter class:
Description Action FileWriter( Creates a FileWriter object String fileName) representing the file with the specified name. String fileName, representing the file with the specified boolean append) name. If append is true, bytes will be written to the end of the file rather than the beginning. File file) representing the specified File object. IOException occurs if a file can’t be opened for output. Copyright © 2000 W. W. Norton & Company. All rights reserved.

107 Writing to a Text File The FileWriter class has no methods, although it does inherit methods for writing characters from its superclasses. In most cases, it’s best to create a different kind of object to do the actual writing to a FileWriter object. The BufferedWriter class is designed for this purpose. Using BufferedWriter provides greater efficiency than using FileWriter directly. Copyright © 2000 W. W. Norton & Company. All rights reserved.

108 Writing to a Text File The single-argument BufferedWriter constructor accepts a FileWriter object (as well as other writer objects) as its argument: FileWriter fileOut = new FileWriter(filename); BufferedWriter bufOut = new BufferedWriter(fileOut); BufferedWriter provides only a limited set of methods, so it’s usually more convenient to use the methods in the PrintWriter class instead. PrintWriter provides the familiar print and println methods. Copyright © 2000 W. W. Norton & Company. All rights reserved.

109 Writing to a Text File A BufferedWriter object (as well as any writer or output stream object) can be passed to the PrintWriter constructor: PrintWriter out = new PrintWriter(bufOut); The PrintWriter class supports the print method, which is capable of writing objects as well as values of the primitive types: out.print(3.14); out.print("Testing..."); When print is used to write an object, the object’s toString method is called. Copyright © 2000 W. W. Norton & Company. All rights reserved.

110 Writing to a Text File The PrintWriter class also provides a number of println methods, which are used in the same way as print: out.println(3.14); out.println("Testing..."); Copyright © 2000 W. W. Norton & Company. All rights reserved.

111 Reading from a Text File
The FileReader class is used for reading characters from a text file. As it reads from a file, a FileReader object will automatically convert each byte into the corresponding two-byte Unicode character. The FileReader constructors are analogous to the FileInputStream constructors. Both constructors throw FileNotFound-Exception if the file can’t be opened for reading. Copyright © 2000 W. W. Norton & Company. All rights reserved.

112 Reading from a Text File
The FileReader class inherits methods for reading characters from its superclasses. In most cases, it’s best to create a Buffered-Reader object to do the actual reading, however. Using BufferedReader provides greater efficiency than using FileReader directly. Also, the BufferedReader class has methods to read whole lines of characters, not just single characters. Copyright © 2000 W. W. Norton & Company. All rights reserved.

113 Reading from a Text File
The single-argument BufferedReader constructor accepts a FileReader object (as well as other kinds of reader objects) as its argument: FileReader fileIn = new FileReader(filename); BufferedReader in = new BufferedReader(fileIn); Copyright © 2000 W. W. Norton & Company. All rights reserved.

114 Reading from a Text File
A partial list of BufferedReader methods: Description Action int read() Reads a character, returning it in int form. int read(char[] cbuf, Reads up to len characters of data int off, into the array cbuf, starting at the int len) position indicated by off. Returns the number of characters read. String readLine() Reads a single line of characters and returns it. All three methods throw IOException if an error occurs. If one of the read methods fails to read any input because it reaches the end of the file, it returns –1. Copyright © 2000 W. W. Norton & Company. All rights reserved.

115 Reading from a Text File
The first version of the read method reads one character from a file. read returns an integer, so a cast is necessary before using the return value as a character. A loop that reads all the characters in a file: while (true) { int charValue = in.read(); if (charValue == -1) break; // End of file reached char inputChar = (char) charValue; } Copyright © 2000 W. W. Norton & Company. All rights reserved.

116 Reading from a Text File
The readLine method reads characters until it encounters a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a line feed. readLine returns a string containing all the characters it read, not including the line-feed and/or carriage-return character. readLine returns null if it was unable to read any characters at all because it reached the end of the input file. Copyright © 2000 W. W. Norton & Company. All rights reserved.

117 Reading from a Text File
A loop that uses readLine to read all the lines in a file: while (true) { String line = in.readLine(); if (line == null) break; } Copyright © 2000 W. W. Norton & Company. All rights reserved.

118 Program: Converting Text to HTML
The ConvertToHTML program converts an ordinary text file into an HTML file. An HTML (Hypertext Markup Language) file is a text file that contains formatting commands, known as tags. These commands are used by a browser to format the file for display. Copyright © 2000 W. W. Norton & Company. All rights reserved.

119 A Sample Text File Copyright © 2000 W. W. Norton & Company.
All rights reserved.

120 Running the ConvertToHTML Program
The ConvertToHTML program expects the name of a text file to be specified on the command line: java ConvertToHTML norton.txt The program will create a file with the same name, but with the extension .html. Copyright © 2000 W. W. Norton & Company. All rights reserved.

121 Copyright © 2000 W. W. Norton & Company.
All rights reserved.

122 Viewing norton.html in a Browser
Copyright © 2000 W. W. Norton & Company. All rights reserved.

123 Program Behavior The ConvertToHTML program will use the first line in the original file as the text for both the <TITLE> and <H2> tags. Each blank line will be replaced by the line <P> Nonblank lines after the first one are copied to the HTML file without change. Certain characters have a special meaning in HTML, including &, <, and >. The program should (but does not) replace these characters by special codes if they appear in the original file. Copyright © 2000 W. W. Norton & Company. All rights reserved.

124 ConvertToHTML.java // Converts an ordinary text file to an HTML file
import java.io.*; public class ConvertToHTML { public static void main(String[] args) { // Terminate program if number of command-line arguments // is wrong if (args.length != 1) { System.out.println("Usage: java ConvertToHTML file"); System.exit(-1); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

125 // Call the generateHTMLFile method, which converts the
// original file to an HTML file. Terminate the program // if an exception occurs. try { generateHTMLFile(args[0]); } catch (IOException e) { System.out.println("Error: " + e.getMessage()); System.exit(-1); } // Returns a file name that is identical to fileName, but // with the extension changed to .html private static String createHTMLFileName(String fileName) { int index = fileName.lastIndexOf("."); if (index != -1) fileName = fileName.substring(0, index); return fileName + ".html"; Copyright © 2000 W. W. Norton & Company. All rights reserved.

126 // Generates an HTML file containing the contents of the
// original file, with HTML tags added private static void generateHTMLFile(String originalFile) throws IOException { // Open the original file for reading FileReader fileIn = new FileReader(originalFile); BufferedReader in = new BufferedReader(fileIn); // Determine the name of the HTML file by changing the // extension of the original file name to .html String newFile = createHTMLFileName(originalFile); // Open the HTML file for writing FileWriter fileOut = new FileWriter(newFile); BufferedWriter bufOut = new BufferedWriter(fileOut); PrintWriter out = new PrintWriter(bufOut); Copyright © 2000 W. W. Norton & Company. All rights reserved.

127 // Read the first line of the original file. Terminate
// the program if the original file is empty. String firstLine = in.readLine(); if (firstLine == null) { System.out.println("File is empty"); System.exit(-1); } // Write a series of tags to the HTML file, using the // first line of the original file for the <TITLE> and // <H2> tags. out.println("<HTML>"); out.println("<HEAD>"); out.println("<TITLE>" + firstLine + "</TITLE>"); out.println("</HEAD>"); out.println("<BODY>"); out.println("<H2>" + firstLine + "</H2>"); Copyright © 2000 W. W. Norton & Company. All rights reserved.

128 // Copy the remaining lines of the original file to the
// HTML file, replacing each empty line with a <P> tag while (true) { String currentLine = in.readLine(); if (currentLine == null) break; if (currentLine.length() == 0) out.println("<P>"); else out.println(currentLine); } // Write the closing tags to the HTML file out.println("</BODY>"); out.println("</HTML>"); // Close both files in.close(); out.close(); Copyright © 2000 W. W. Norton & Company. All rights reserved.

129 14.7 Reading and Writing Objects
Objects can be written to a file and later read back in. A file that contains objects is always a binary file. Writing an object to a file involves saving the values of all the object’s instance variables. In addition, a “tag” will need to be saved to indicate the object’s type. If any of the values stored in an object are references to other objects, those objects will need to be saved as well. Copyright © 2000 W. W. Norton & Company. All rights reserved.

130 Serialization When objects are written to a file, Java uses a process known as serialization. Java automatically adds information to each object to identify its class. If the object contains references to other objects, those objects are stored as well. Each object is stored only once, regardless of the number of references to it. Copyright © 2000 W. W. Norton & Company. All rights reserved.

131 The Serializable Interface
The Serializable interface is used to indicate that a class is serializable. Serializable belongs to the java.io package. A number of classes in the Java API implement the Serializable interface. If a class is serializable, then all its subclasses are as well. Copyright © 2000 W. W. Norton & Company. All rights reserved.

132 The Serializable Interface
To make a class serializable, the words implements Serializable are added to its declaration: class MyClass implements Serializable { } Serializable is empty, so MyClass doesn’t need to contain any particular methods. Copyright © 2000 W. W. Norton & Company. All rights reserved.

133 The Serializable Interface
Two other conditions are required in order for a class to be serializable: If any of the instance variables in the class contain objects, these objects must belong to serializable classes. The class’s direct superclass must have a no-arg constructor or be serializable. If a program tries to write an object that’s not serializable, a NotSerializableException will occur. Copyright © 2000 W. W. Norton & Company. All rights reserved.

134 Writing Objects In order to write objects to a file, an instance of the ObjectOutputStream class is needed. This instance will be layered on top of an instance of the FileOutputStream class: FileOutputStream fileOut = new FileOutputStream(fileName); ObjectOutputStream out = new ObjectOutputStream(fileOut); The argument to the ObjectOutputStream constructor can be any kind of output stream. The constructor may throw IOException. Copyright © 2000 W. W. Norton & Company. All rights reserved.

135 Writing Objects The most important ObjectOutputStream method is writeObject, which is used to write an object to a stream. The parameter to writeObject has type Object, so any object can be passed to writeObject. The String class implements the Serializable interface, so a string can be passed to writeObject: out.writeObject("Testing..."); Copyright © 2000 W. W. Norton & Company. All rights reserved.

136 Writing Objects Exceptions that can arise as a result of calling writeObject: IOException InvalidClassException NotSerializableException InvalidClassException and NotSerializableException are indirect subclasses of IOException, so a catch block for IOException will handle those as well. Copyright © 2000 W. W. Norton & Company. All rights reserved.

137 Writing Objects The remaining ObjectOutputStream methods closely resemble DataOutputStream methods. These methods are used to write other types of data, such as integers, floating-point numbers, and characters. By providing these methods, the ObjectOutputStream class allows a file to contain a mixture of objects and values of the primitive types. Copyright © 2000 W. W. Norton & Company. All rights reserved.

138 Reading Objects Before objects can be read, an instance of the ObjectInputStream class must be created: FileInputStream fileIn = new FileInputStream(fileName); ObjectInputStream in = new ObjectInputStream(fileIn); The argument to the ObjectInputStream constructor can be any kind of input stream. Copyright © 2000 W. W. Norton & Company. All rights reserved.

139 Reading Objects The ObjectInputStream constructor may throw IOException and StreamCorrupted-Exception (the format of the underlying file is wrong). A catch block for IOException can handle both exceptions. Objects are read from an ObjectInputStream by calling the readObject method. readObject returns an Object value, which can then be cast to the proper type: String str = (String) in.readObject(); Copyright © 2000 W. W. Norton & Company. All rights reserved.

140 Reading Objects Exceptions that can arise as a result of calling readObject: ClassNotFoundException—The Java interpreter is unable to locate the class to which the object belongs. InvalidClassException—There’s a problem with the class to which the object belongs. IOException—The underlying stream has a problem. OptionalDataException—The readObject method encountered unexpected data. StreamCorruptedException—The readObject method encountered an inconsistency in the data. Copyright © 2000 W. W. Norton & Company. All rights reserved.

141 Reading Objects A catch block for IOException will also handle InvalidClassException, OptionalDataException, and StreamCorruptedException. ClassNotFoundException is not a subclass of IOException, however, so it will need a separate catch block. Copyright © 2000 W. W. Norton & Company. All rights reserved.

142 Reading Objects The remaining ObjectInputStream methods are used to read other types of data, such as integers, floating-point numbers, and characters. These methods closely resemble DataInputStream methods. Copyright © 2000 W. W. Norton & Company. All rights reserved.

143 Reading and Writing Entire Data Structures
Data structures are objects, so they can be written to a file with a single method call. An example of writing an array to a file: int[] a = {1, 2, 3}; try { FileOutputStream fileOut = new FileOutputStream(fileName); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(a); out.close(); } catch (IOException e) { System.out.println(e.getMessage()); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

144 Reading and Writing Entire Data Structures
Code that reads the array back in: int[] a; try { FileInputStream fileIn = new FileInputStream(fileName); ObjectInputStream in = new ObjectInputStream(fileIn); a = (int[]) in.readObject(); in.close(); } catch (IOException e) { System.out.println(e.getMessage()); } catch (ClassNotFoundException e) { } Copyright © 2000 W. W. Norton & Company. All rights reserved.

145 Reading and Writing Entire Data Structures
Similar code can be used to write a vector or other data structure and then read it later. When serializing a data structure, make sure that the elements of the data structure are serializable. Otherwise, a NotSerializableException will occur when the program is executed. Copyright © 2000 W. W. Norton & Company. All rights reserved.

146 14.8 Case Study: A Phone Directory (Revisited)
The original PhoneDirectory program (Section 5.8) allowed the user to enter names and numbers as well as look up existing names. Unfortunately, the names and phone numbers were lost when the program terminates. The new version of PhoneDirectory will save the names and numbers in a file when it terminates. When the program is run the next time, it restores the names and numbers by reading from the file. Copyright © 2000 W. W. Norton & Company. All rights reserved.

147 Changes to the PhoneDirectory Program
Other differences between the old and new versions of PhoneDirectory: PhoneRecord objects will be stored in a vector rather than an array. The new program relies on helper methods instead of a single main method. Helper methods: addNumber—Implements the a (add) command findNumber—Implements the f (find) command saveRecords—Saves records in a file readRecords—Reads records from the same file Copyright © 2000 W. W. Norton & Company. All rights reserved.

148 Changes to the PhoneDirectory Program
saveRecords will save the vector of records in a file named records.dat. If readRecords is unable to read from the records.dat file (or the file doesn’t exist), the method will display a message and create an empty vector. The PhoneRecord class is the same as before, except that implements Serializable will be added to the class declaration. Copyright © 2000 W. W. Norton & Company. All rights reserved.

149 PhoneDirectory2.java // Program name: PhoneDirectory2
// Author: K. N. King // Written: // // Stores names and telephone numbers and allows phone // numbers to be looked up. The user is given a menu of // three commands: // a - Add a new phone number // f - Find a phone number // q - Quit // The "a" command prompts the user to enter a name and a // number, which are then stored in the program's database. Copyright © 2000 W. W. Norton & Company. All rights reserved.

150 // The "f" command prompts the user to enter a name; the
// program then displays all matching names in the database, // along with the corresponding phone numbers. It is not // necessary to enter the entire name; all names that begin // with the specified characters will be displayed. The "f" // command ignores the case of letters when looking for // matching names. // // The "q" command causes the program to terminate. The names // and numbers are saved in a file named "records.dat". When // the program is run the next time, it will open the file // and read the records. import java.io.*; import java.util.*; import jpb.*; Copyright © 2000 W. W. Norton & Company. All rights reserved.

151 public class PhoneDirectory2 { // Class variables
private static final String DATA_FILE = "records.dat"; private static Vector records; public static void main(String[] args) { // Read records from data file readRecords(); // Display list of commands System.out.println("Phone directory commands:\n" + " a - Add a new phone number\n" + " f - Find a phone number\n" + " q - Quit\n"); Copyright © 2000 W. W. Norton & Company. All rights reserved.

152 // Read and execute commands while (true) {
// Prompt user to enter a command SimpleIO.prompt("Enter command (a, f, or q): "); String command = SimpleIO.readLine().trim(); // Determine whether command is "a", "f", "q", or // illegal; execute command if legal. if (command.equalsIgnoreCase("a")) { // Command is "a". Call addNumber to add a new // name and number to the database addNumber(); } else if (command.equalsIgnoreCase("f")) { // Command is "f". Call findNumber to find phone // numbers that match the user's criteria. findNumber(); Copyright © 2000 W. W. Norton & Company. All rights reserved.

153 } else if (command.equalsIgnoreCase("q")) {
// Command is "q". Save records in data file and // terminate program. saveRecords(); return; } else { // Command is illegal. Display error message. System.out.println("Command was not recognized; " + "please enter only a, f, or q."); } System.out.println(); Copyright © 2000 W. W. Norton & Company. All rights reserved.

154 ///////////////////////////////////////////////////////////
// NAME: addNumber // BEHAVIOR: Prompts the user for a name and number, // then creates a phone record and stores it in // the records vector. // PARAMETERS: None // RETURNS: Nothing private static void addNumber() { SimpleIO.prompt("Enter new name: "); String name = SimpleIO.readLine().trim(); SimpleIO.prompt("Enter new phone number: "); String number = SimpleIO.readLine().trim(); records.addElement(new PhoneRecord(name, number)); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

155 ///////////////////////////////////////////////////////////
// NAME: findNumber // BEHAVIOR: Prompts the user for a search key. Searches // the records vector for records whose names // begin with the search key. Prints these // names and the corresponding phone numbers. // PARAMETERS: None // RETURNS: Nothing private static void findNumber() { SimpleIO.prompt("Enter name to look up: "); String key = SimpleIO.readLine().trim().toLowerCase(); for (int i = 0; i < records.size(); i++) { PhoneRecord currentRecord = (PhoneRecord) records.elementAt(i); String name = currentRecord.getName().toLowerCase(); if (name.startsWith(key)) System.out.println(currentRecord.getName() + " " + currentRecord.getNumber()); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

156 ///////////////////////////////////////////////////////////
// NAME: readRecords // BEHAVIOR: Restores the records vector to its previous // state by reading it (as a single object) // from the data file. Creates an empty vector // if the file does not exist or cannot be // read. // PARAMETERS: None // RETURNS: Nothing private static void readRecords() { try { FileInputStream fileIn = new FileInputStream(DATA_FILE); ObjectInputStream in = new ObjectInputStream(fileIn); records = (Vector) in.readObject(); in.close(); } catch (Exception e) { System.out.println(DATA_FILE + " does not exist or " + "cannot be read\n"); records = new Vector(); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

157 ///////////////////////////////////////////////////////////
// NAME: saveRecords // BEHAVIOR: Saves the records vector (as a single // object) by writing it to the data file. // PARAMETERS: None // RETURNS: Nothing private static void saveRecords() { try { FileOutputStream fileOut = new FileOutputStream(DATA_FILE); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(records); out.close(); } catch (IOException e) { System.out.println("Error writing to " + DATA_FILE); } Copyright © 2000 W. W. Norton & Company. All rights reserved.

158 // Represents a record containing a name and a phone number
class PhoneRecord implements Serializable { private String name; private String number; /////////////////////////////////////////////////////////// // NAME: PhoneRecord // BEHAVIOR: Constructs a phone record containing the // specified name and phone number // PARAMETERS: personName - name of a person // phoneNumber - phone number for that person public PhoneRecord(String personName, String phoneNumber) { name = personName; number = phoneNumber; } Copyright © 2000 W. W. Norton & Company. All rights reserved.

159 ///////////////////////////////////////////////////////////
// NAME: getName // BEHAVIOR: Returns the name stored in this record // PARAMETERS: None // RETURNS: The name stored in this record public String getName() { return name; } // NAME: getNumber // BEHAVIOR: Returns the phone number stored in this // record // RETURNS: The phone number stored in this record public String getNumber() { return number; Copyright © 2000 W. W. Norton & Company. All rights reserved.


Download ppt "Files Chapter 14 Copyright © 2000 W. W. Norton & Company."

Similar presentations


Ads by Google