CS 151 Fall 2007 Lab 11

Reading Input, Writing Output, Handling Exceptions

 

The main goal for this lab is to learn more about reading input from and writing output to files.  As we will see, this is often an error prone exercise.  Consequently, file manipulation programs also require quite a bit of error checking and handling which is primarily done in Java by throwing and catching exceptions.  Special thanks to Prof. Jen Dillion who teaches Biostatistics for the idea to use U.N. data and for extracting the data from the U.N.'s site for me.

 

  1. Open BlueJ either by selecting it from the Dock or navigating to it in the Applications folder and double clicking it.

  2. Mount your network directory/folder so that you can access the lab after you leave Olin 323.  Go to the Finder and from the Go menu select Connect to Server....  Type afp://fileserver1 or choose it from the list of selections and select the Personal volume when prompted.

  3. From the Project menu select New Project.  Select your computer from the drop down menu.  Then scroll down and open the Volumes folder and then the Personal folder inside it.  Scroll down the long list of folders until your find yours.  Create a project called "Lab11" in your personal network folder.

  4. Download the compressed file data.zip.  Copy it to your newly created Lab11 project folder in the Finder (not in BlueJ).  By default, data.zip should be on the Desktop, so you can just drag and drop it to your personal folder.  Once you've done that, double-click data.zip to extract the multiple files it contains.

 

  1. Create a class called UNDataReader and remove the default instance variable and method that BlueJ puts in the class.  Create the usual static main method and don't forget that it takes a parameter called args whose type is an array of Strings.

  2. In the very first line of the class, add an import statement for the Scanner class from the java.util package.  Add a second import statement for all needed classes (using the * wildcard) from the java.io package.

 

  1. Create a variable of type Scanner in the main method called console and assign it a Scanner object that reads from the Terminal window.  Add a printed message prompting the user for the name of a file to read data from.  Add a line that reads the user's response and stores it in a String variable, e.g. called fileName.  Compile your code and fix any errors.

 

  1. Next we want to create a Scanner object that reads from the user-specified file name instead of from the Terminal.  Unfortunately, we can't just create a Scanner using the file name.  Feel free to try it and see what happens.  Instead we first create a FileReader using the file name and then create a Scanner that uses the FileReader.  If you think this is complicated, before this version of Java it was even worse!

 

  1. Define a variable of type FileReader called reader.  Assign to it a FileReader object constructed with the user-provided filename as a parameter, e.g. reader = new FileReader(filename).  Try to compile after adding this line.  The class won't compile because the constructor for FileReader may throw a FileNotFoundException if it can't find the file.  All the exceptions (error conditions) we have encountered so far have been unchecked exceptions.  Java doesn't require that we explicitly handle unchecked exceptions.  Checked exceptions such as FileNotFoundException, on the other hand, may arise due to circumstances beyond our control.  Java requires our methods to explicitly manage such errors.  We can either catch the error and take some action or simply throw (pass on) the error and let some higher level method deal with the problem.  The second approach is suitable here.  So, fix the problem by add the phrase throws FileNotFoundException after the declaration of/interface for main but before its body (the part in {}).  Compile again and the compiler should now be happy.

 

  1. Create a second Scanner variable called input and initialize it with a new Scanner using reader as a parameter.

 

  1. Open the file cinema_data1.txt using TextEdit or any editing/word processing application.  We want to read in the three entries (usually called fields) from each line (usually called a record).  See the Java Class documentation for more information on Scanner's methods.  We will use nextInt(), next(), and nextDouble to read in the data.  We will also use hasNextLine() to test when we have reached the end of the file and there is no more data to read.

 

  1. Add the following lines to you main method, to read and display the contents of the first record in the file:

    // this first line is just a header
    System.out.println("Country
    Code, Country Name, Cinema Attendance");
    System.out.println(input.nextInt() + ", " + input.next() + ", " + input.nextDouble());

 

  1. Compile and run it.  Enter cinema_data1.txt when prompted for the file name.  Run it again and this time enter the name of a file that doesn't exist, e.g. hello.txt.  As expected, this causes a FileNotFoundException and brings everything to a screeching halt.  Not a very pleasant experience for the user of your program!

 

  1. Multiply the attendance by one million so that it displays the actual integer number of people.  By default, double's larger than a certain amount are displayed in exponential notation.  Try casting to get an integer displayed.  Also remove the country code from the displayed information.  Even if you don't want to display it you still need to read it!  Try not reading it and see what happens.  Add a line that just calls nextInt() but doesn't do anything with the integer it returns.  It reads the country code and basically forgets it.  At the very end of the main method, add a line that calls the close() method on the FileReader, e.g. reader.close().  It's good practice to always close any files you opened.  When you try to compile you get an error about an unreported IOException.  Change the description of your main method to "throws IOException" instead of FileNotFoundException.  Why doesn't it complain about FileNotFoundException now (see p.434 in your book for the answer)?

 

  1. Add a while loop to read and display all the records in the file.  The Scanner method hasNextLine() allows you to peek ahead and see if there is another record to be read, without actually doing anything with that record.  Keep reading and displaying the contents of each record until there are no more records.  Compile and run using cinema_data1.txt as the file.

 

  1. Now try it with cinema_data2.txt.  Why don't things work the way they should?  You need to keep reading words of the country's name until you come to a double.  You can use the method hasNextDouble() to check if the next thing you will read in next is a double or not.  Use a while loop to build up the country's name word by word in a String variable.

 

  1. Once you can successfully read cinema_data2.txt, try cinema_data_full.txt.  This is the original data file as downloaded from the United Nation's web site.  Open the file to see what's causing the problem.  You can read and discard a line by calling the nextLine() method and not doing anything with the String it returns.  How would your fix change if the number of initial descriptive lines wasn't always two?

 

  1. Try it again. Now what's the problem?  Look at the records for Portugal and Zimbabwe to get an idea.

 

  1. Did you finally get the whole file read and displayed?  Congratulations.

 

  1. Try to write out the parts of the file we want (just country name, attendance) to a new file called "clean_cinema_data.txt" in addition to displaying it on the screen.  Add the following near the beginning of your main method:

    PrintWriter output = new PrintWriter("clean_cinema_data.txt");
     
    To print to the file use output.print() or output.println().  Print to both the screen and the file and make sure the same thing goes both places.   Don't forget to close output at the end of your main method.  This is even more important for output writing than for input reading.  Failing to close() may result in lost information.