• Tidak ada hasil yang ditemukan

Example: Comparing Two Files

Dalam dokumen Pelajari tentang Advanced topics in Java (Halaman 191-195)

Working with Files

7.4 Example: Comparing Two Files

Consider the problem of comparing two files. The comparison is done line by line until a mismatch is found or one of the files comes to an end. Program P7.1 shows how we can solve this problem.

Program P7.1

import java.io.*;

import java.util.*;

public class CompareFiles {

public static void main(String[] args) throws IOException { Scanner kb = new Scanner(System.in);

System.out.printf("First file? ");

String file1 = kb.nextLine();

System.out.printf("Second file? ");

String file2 = kb.nextLine();

Scanner f1 = new Scanner(new FileReader(file1));

Scanner f2 = new Scanner(new FileReader(file2));

String line1 = "", line2 = "";

int numMatch = 0;

while (f1.hasNextLine() && f2.hasNextLine()) { line1 = f1.nextLine();

line2 = f2.nextLine();

if (!line1.equals(line2)) break;

++numMatch;

}

if (!f1.hasNextLine() && !f2.hasNextLine())

System.out.printf("\nThe files are identical\n");

else if (!f1.hasNextLine()) //first file ends, but not the second System.out.printf("\n%s, with %d lines, is a subset of %s\n", file1, numMatch, file2);

else if (!f2.hasNextLine()) //second file ends, but not the first System.out.printf("\n%s, with %d lines, is a subset of %s\n", file2, numMatch, file1);

else { //mismatch found

System.out.printf("\nThe files differ at line %d\n", ++numMatch);

System.out.printf("The lines are \n%s\n and \n%s\n", line1, line2);

}

f1.close();

f2.close();

} //end main

} //end class CompareFiles The program does the following:

It prompts for the names of the files to be compared; if any of the files does not exist, a

•฀

FileNotFoundException will be thrown.

It creates two

•฀ Scanners, f1 and f2, one for each file.

It uses

•฀ hasNextLine to check whether a file has more lines to read; if true, there is at least another line to read, and if false, the end of the file has been reached.

The variable

•฀ numMatch counts the number of matching lines. One line from each file is read.

If they match, 1 is added to numMatch, and another pair of lines is read. The while loop exits naturally if one (or both) of the files comes to an end; we break out of the loop if a mismatch occurs.

If the first file contains this:

one and one are two two and two are four three and three are six four and four are eight five and five are ten six and six are twelve and the second file contains this:

one and one are two two and two are four three and three are six four and four are eight this is the fifth line six and six are twelve

the program will print the following:

The files differ at line 5 The lines are

five and five are ten and

this is the fifth line

7.5 The try . . . catch Construct

When a program is trying to read data, errors can arise. There may be a problem with the device, we may be trying to read beyond the end of the file, or the file we are asking to read from may not even exist. Similarly, when we attempt to write data to a file, the device may be locked or unavailable, or we may not have write permission. In such cases, Java throws an IO (input/output) Exception”.

Whenever there is the possibility that a method may trigger an I/O error, either by performing some I/O

operation itself or by calling a method that does, Java requires that the method declare this. One way to do so is to use throws IOException in the method header, as in the following:

public static void main(String[] args) throws IOException {

Another way to handle input/output errors is to use the try . . . catch construct. Suppose a program contains this statement:

Scanner in = new Scanner(new FileReader("input.txt"));

When run, if the program cannot find a file called input.txt, it will halt with a “file not found exception” error message. We can avoid this as follows:

try {

Scanner in = new Scanner(new FileReader("input.txt"));

}

catch (IOException e) {

System.out.printf("%s\n", e);

System.out.printf("Correct the problem and try again\n");

System.exit(1);

}

The try block consists of the word try followed by a block (zero or more statements enclosed in braces). Java attempts to execute the statements in the block.

The catch part consists of the word catch followed by an “exception type” in brackets, followed by a block. In this example, we expect that an I/O exception might be thrown, so we use IOException e after catch. If an exception is indeed thrown, the statements in the catch block are executed.

In this example, suppose the file input.txt exists. The Scanner in… statement will succeed, and the program will continue with the statement after the catch block. But if the file does not exist or is not available, the exception will be thrown and caught with the catch part.

When this happens, the statements, if any, in the catch block are executed. Java lets us put any statements in a catch block. In this case, we print the contents of the exception object, e, and a message, and the program exits. When run, with no file input.txt, this code prints the following:

java.io.FileNotFoundException: input.txt Correct the problem and try again

The program does not have to exit. If the exit statement were omitted, the program would simply continue with the statement, if any, after the catch block. If we want, we could also call another method to continue execution.

To continue the example, consider the following:

try {

Scanner in = new Scanner(new FileReader("input.txt"));

n = in.nextInt();

}

We attempt to read the next integer from the file. Now, many things can go wrong: the file may not exist, the next item in the file may not be a valid integer, or there may be no “next” item in the file. These will throw “file not found,” “input mismatch,” and “no such element” exceptions, respectively. Since these are all subclasses of the class Exception, we can catch them all with the following:

catch (Exception e) {

System.out.printf("%s\n", e);

System.out.printf("Correct the problem and try again\n");

System.exit(1);

}

When the file is empty, this code prints this:

java.util.NoSuchElementException Correct the problem and try again

When the file contains the number 5.7 (not an integer), it prints this:

java.util.InputMismatchException Correct the problem and try again

If necessary, Java allows us to catch each exception separately. We can have as many catch constructs as needed.

In this example, we could write the following:

try {

Scanner in = new Scanner(new FileReader("input.txt"));

n = in.nextInt();

}

catch (FileNotFoundException e) { //code for file not found }

catch (InputMismatchException e) { //code for “invalid integer” found }

catch (NoSuchElementException e) { //code for “end of file” being reached

Sometimes, the order of the catch clauses matters. Suppose we want to catch “file not found” separately from all other exceptions. We may be tempted to write this:

try {

Scanner in = new Scanner(new FileReader("input.txt"));

n = in.nextInt();

}

catch (Exception e) {

//code for all exceptions (except “file not found”, presumably) }

catch (FileNotFoundException e) { //code for file not found }

This code would not even compile! When Java reaches the last catch, it will complain that

FileNotFoundException has already been caught. This is because FileNotFoundException is a subclass of Exception.

To fix the problem, we must put catch (FileNotFoundException e) before catch (Exception e).

In general, subclass exceptions must come before the containing class.

Dalam dokumen Pelajari tentang Advanced topics in Java (Halaman 191-195)