CS 257 Project 2 TechNote


TechNotes are provided to add some practical tips and design hints for our projects. More TechNotes will be posted as new projects are assigned, containing answers to questions about the projects, and with implementation tips after I see what kinds of designs come in.

All of this information is in the CS 157 and 257 textbooks, and the online Java docs, but pulling it together in one place will hopefully make parts of the project easier to develop.


Reading Files

There are several approaches to reading files in Java, and at least two are described in the CS 157 text, Java: An Eventful Approach. One relatively straightforward approach, using Scanner, is not. This is the subject of this technote. The trick, as with any code involving I/O, is to get the exception handling right.

To read a file with Scanner, you first must provide a File object which represents the opened file. This would be easy:

   File f = new File(filename); // filename is a String

except that the File constructor can throw a checked exception, so Java requires that it be called in a try/catch block.

Similarly, telling a Scanner to do its reading from the file is apparently easy:

   Scanner reader = new Scanner(f); // f represents the open file

However, again the Scanner constructor might throw an exception, so this too must be wrapped in a try/catch block.

Can they be combined? Yes! Having a look at the online docs for File and Scanner, we see that each throw different exception types. We can use two catch blocks to check for each type:

try {
File f = new File(filename);
Scanner reader = new Scanner(f);
// now we can start reading data from the file thrown
// the Scanner, using the usual methods: nextInt, next, hasNext
} catch (FileNotFoundException ex) {
// opening the file didn't work
// print out some error message, exit, or recover from error
} catch (NullPointerException ex) {
// connecting Scanner to the file didn't work
// print out some error message, exit, or recover from error
}

Now, as described in the Chapter 19 of the CS157 text, all these classes need to be imported. We have examples from previous work for importing Scanner; for the rest, importing from java.io.* should suffice.

One question still: where does the filename passed to File come from? You provide it, when you run the program. Remember the argument to main, String[] args? Normally the args array is empty, but if you provide command-line arguments when you run java, those go in the array. So for example we invoke the Java Virtual Machine this way:

 $ java SearchesTest dictionary.txt

it will start executing SearchesTest as usual, but now the first slot of the args array will contain the string dictionary.txt. So instead of filename, we can use args[0] as the argument to the File constructor.