T-Th 9:05
or
T-Th 11:15
in Phillips 101

CS 1110: Introduction to Computing Using Java

Spring 2012

Reading Files

Because of a last minute change in this lab, there is no handout for this lab. Sorry about that. All of today's lab will consist of finishing the class Reading.java; there is nothing to write on paper.

This lab discusses input (e.g. reading a file). After the lab, study section 5.9 of the text. Better yet, listen to the lectures on lesson page 5-7 of the ProgramLive CD. The lectures are much clearer than the paper version.

Requirements For This Lab

Start this lab by downloading file lab10.zip putting its contents in a new directory. It contains these files:

Once you have done that, open the .java file in DrJava and compile it. The only thing that you need to do in this lab is to complete the method contains in Reading.java; everything else below is optional. When you have done this, show your file to your instructor.

As always, you should try to finish the lab during your section. However, if you do not finish during section, you have until the beginning of lab next week to finish it. You should always do your best to finish during lab hours; remember that labs are graded on effort, not correctness.


Understanding Streams

A "stream" is a sequence of data values that is processed — either read or written — from beginning to end. When the data is being read, or input, the stream is called an "input stream"; when it is being written, or output, the stream is called an "output stream". Input/output of streams is done in Java using classes in package java.io. Remember to import this package when you try anything in the Interactions pane below.

The basic way to create an input stream for a file is by creating an instance of class FileReader:

FileReader fr= new FileReader(an arg that describes what file to read);

And the standard way to read using FileReader fr is to read one character at a time, using function

fr.read()

This is too low-level for us. We would like to be able to read not one character at a time but one line at a time. For this, we use class BufferedReader. The is another type of a wrapper class in that you wrap it around a FileReader to add functionality.

Instead of the above, use the following command:

FileReader fr= new FileReader(an arg that describes what file to read);
BufferedReader br= new BufferedReader(fr);

The BufferedReader named in br now wraps the FileReader for your file. Now, the execution of

String line = br.readLine();

reads the next line of the file and stores it in variable line. If there are no more lines to read, null is stored in line. We will see how to use this later.


Using a JFileChooser Dialog Box

In order to read a file, you have to indicate which file should be read. The easiest way to do this is to use a dialog window to navigate to the appropriate directory and select the file. For this, we use an instance of class JFileChooser, in package javax.swing. Execute the following in the Interactions pane (assuming that br is already declared):

br = Reading.getReader(null);

A dialog box opens. Its title is "Choose input file". And it allows you to navigate anywhere you want and then select a file. Do a bit of navigating and select a file. Then take a look at function getReader(String). Here is what it does:

   1. Declare local variable jd of class JFileChooser
   2. Store in jd a new instance of class JFileChooser
In the new expression new JFileChooser(), you have no control over the directory that appears in the dialog window initially. In the new expression new JFileChooser(p), String p is supposed to be a path on your computer of the directory to open in the dialog window. This choice allows you to dispense with a lot of navigating.
   3. Set the title of jd to "Choose input file".
   4. Execute of jd.showOpenDialog(null);
This causes the dialog window to open on your monitor, and the program pauses until you have closed it. Nothing happens until you have chosen a file (or canceled the interaction).
   5. Create a new FileReader with the file that you selected
The name of this file is jd.getSelectedFile(). The name is stored in fr.
   6. Create and return a BufferedReader that is attached to fr.

The function for obtaining the next line from a BufferedReader br is:

br.readLine()      // = the next line of BufferedReader br —null if there are no more lines

In the Interactions pane, you can continue to evaluate br.readLine(). Each time you do it, the next line of the file you selected is printed. Try it.


Processing the Lines of a File

Function lines in class Reading illustrates the basic way of processing the lines of a file given by a BufferedReader. In the Interactions pane, put a call on this method and let it read some file —you will see how many lines the file has in it.

Study this method. Any loop that you write that processes a file should be similar to this one —the "processing" of each line will change, but the basic structure of the loop that does the processing will not. Note that this method contains a while-loop. Here are important points:

  1. The first line is read before the while loop and stored in variable lin.
    lin will be null if the file is empty.
  2. The loop stops when lin is null, indicating that there are no more lines in the file.
  3. The repetend first processes the line given by variable lin and then reads the next line into lin.

The header of the method contains the following: throws IOException. It is needed because function br.readLine() might create some sort of I/O (input/output) error, and this is how we handle it. We talked about exceptions previously in the course.


Write Your Own Method

Reading a File

Write the body of function contains that is declared in class Reading (and test it). If you are smart, you will write a JUnit testing class with a procedure to test this method, though that is not required.

The specification of this method is including in Reading.java. The method takes a parameter s and checks to see if the value in this parameter is a line in the file of the user. For example, we could use the method call

Reading.contains("djg17")
to see whether the Cornell netid djg17 appears in one of the two files cms.txt and peop.txt.

This is the only part of the lab that is required. Please show your code to you instructor when you are done.


Writing Files (Optional)

This section describes a task that you might have fun doing. It is something we had to do in previous semesters when dealing with prelim conflicts. The task is to read in two files of netids, say cms.txt and peop.txt (containing netids for our course and netids for a particular math course), and create a file that contains all netids that are in both files. You can assume that the two files are already sorted by netids. This is nice example works with input/output files and also contains an interesting loop. It can be simple or comlpicated, depending how you write it.

Please read on and learn about writing files, but you do not have to complete this task for this lab.

Writing files is not much different from reading them. Procedure getWriter obtains the name of a file (in a particular directory) to write, using a JFileChooser window that is placed on the monitor using showSaveDialog (instead of showOpenDialog). The procedure uses the resulting file as an argument in the constructor call of a PrintStream object.

Try this in the Interactions pane:

PrintStream v= Reading.getWriter();

When the dialog window opens, navigate to a directory and select a file name or type in a completely different one; then you can select one and then change it slightly. Be careful. You will not want to overwrite an existing file, but this can easily happen.

Now, type

v.println("first line in the file");
v.close();

The first statement writes a line to the file. You can write as many lines as you wish. The second statement should be used to close the file.

After these statements are executed, look at the directory where the file was written, open the file, and look at it.

Now, write (and test) the body of procedure Reading.netIds. Note that it has a series of comment-statements; each is a statement to do something, written in English. Write the Java implementation of each comment directly under the comment and follow the implementation with a blank line.