Lab 17: File I/O and exceptions

This lab gives you a chance to work with reading and writing files, including dealing with exceptions.

1. Introduction

In class yesterday we wrote most of a program to play one side of the game Twenty Questions. The program is even designed to “learn” as it plays, collecting additional questions and guesses into a decision tree. In today's lab, you will be extending that program.

To get started, clone the repository:

hg clone /cslab/class/csci235/labs/lab17
cd lab17

This code is descended from what we had at the end of class. The primary change is that I have filled in a framework for reading and writing the tree of questions and answers.

As you work today, take advantage of the fact that you have a Mercurial repository. Be sure to commit as you complete various features--and especially before you try something that might make a mess.

2. Inspecting the code

There is now a save() method in the Node class and its subclasses. Note how this is documented: it is supposed to save the tree rooted at the node, which is a natural way to recursively save the tree.

There are three new methods at the end of Questions.java. The first two of these need to handle opening the file, including dealing with errors that occur. Neither of them does that yet. readTree() is partially filled in so that when it fails to read the file it constructs a default tree.

The last of the new methods, readNode() is the one that does the important work in reading in a tree: it reads a node (and its children) from the already open file (type Scanner) and constructs the tree. This static method is needed because it can not decide which type of node to instantiate until it reads some information from the file. Completing this will probably require writing one or more new constructors for the node classes.

The main method now expects the program to be run with a single argument, giving the name of the file from which to read the initial tree and to save it on exit.

3. Designing a file format

Your first job is to decide how a tree of questions and answers should be formatted when saved to a file. You will have to be able to figure out as you read whether what you have is a question or an answer; that may be simple if you think about writing one line for each node in the file. Recall that there are several orders in which a tree can be printed--preorder, inorder, and postorder. You and your partner should try playing around with the different orders to figure out which is easiest to read back in. You might even use your editor to create one or more files that contain valid trees.

Add a comment before readNode() that describes the format in which you will save trees.

4. Write it

Complete the reading and saving of trees. You probably want to tackle those one at a time. (I suggest saving as a good place to start.) Take advantage of Mercurial, and be sure to commit at useful points along the way.

5. Improvements

Once you have things working, you can consider making improvements. Right now, the program does not deal well with the user forgetting to supply a filename. You should catch that and print a message; you might also consider supplying a default filename if the user does not. It would also be good to print a message if something goes wrong when trying to save the tree.

6. Handing in

Make a typescript of your program running several times, showing that it learns and saves what it learns. After you end the script, turn in your typescript and source files with the command

/cslab/class/csci235/bin/handin lab17 typescript *.java

Cary Gray
Last modified: Thu Dec 4 08:19:52 CST 2014