Lab 4: Files

Copyright RIT 2009
$Id: writeup.xml,v 1.9 2009/01/05 18:32:18 vcss232 Exp $


Goal

In this lab you work with files in Java. You will learn how to write code that opens a file and reads data from it. Since file operations can throw exceptions you will need to handle that also. You will learn to work with files by writing a small utility program that searches for strings in a text file.

Overview

Ask Dr. Tiger

Objectives

Pre - Lab Work

  1. Review class notes for the preceding week.
  2. Read Liang Chapter sections 8.7-8.8 and 18.1-18.5.
  3. Read the documentation for the following classes: FileReader BufferedReader FileWriter BufferedWriter and PrintWriter

  4. Complete the file exercises found by clicking on http://www.cs.rit.edu/~cs1/Exercises/_Files_and_More.

  5. You can also find additional information on I/O from http://java.sun.com/docs/books/tutorial/essential/io/ in the Java tutorial.

In-Lab Activities

Each lab you will do is separated into a set of activities. Each activity has tasks you must complete and submit for credit. Each activity is graded separately.

Activity #1

This activity is a refresher on command line arguments which were introduced in CS1. Command line arguments are the words entered after you type the command name at the Unix prompt. For example, when you compiled the Rectangle.java and Circle.java files in Lab 3 you used the command:


javac Rectangle.java Circle.java
			

javac is the name of the command. There are two command line arguments: Rectangle.java and Circle.java. Note that spaces separate each argument. If you want to include spaces in an argument then you must surround that argument with quotes, as in:


grep "Computer Science" /etc/motd
			

Remember that command line arguments in a Java program start after the name of the program in the command line. For example, if you type the following command to start the Java program EchoCommandLine.java:


java EchoCommandLine one two three four
			

The command line arguments, as seen by the Java program, would be one, two,three, and four.

To make sure that you understand how to access command line arguments write a Java program called SumArgs which prints the sum of all of its integer command line arguments. For each argument, you must convert it to an integer before adding it to your sum. You can use the parseInt method in Integer for this.

For each argument that is not a valid integer, the program will display the following message:


Bad integer: For input string: "arg"
			

where arg is the bad command line argument. ( The quotes do show up in the output. ) This error message must be sent to standard error (System.err in Java) instead of standard out (System.out in Java). Standard error, which is reserved for error messages, will display in your terminal window just like standard out. You have the same formatting methods available with both outputs. The program must continue summing the remaining arguments after displaying the error message.

When all the valid integer arguments have been summed, the program will display the following message using standard out:


The sum of the arguments is: sum
			

where sum is the total of all the valid arguments. Note that it is possible that none of the arguments are valid, or you may not get any arguments at all. In these cases sum would be zero.

For example, if you run your program with the following command:


				
java SumArgs 1 2 3d4 5 7.6 -3 nAn

			

it must generate the following output:


Bad integer: For input string: "3d4"
Bad integer: For input string: "7.6"
Bad integer: For input string: "nAn"
The sum of the arguments is: 5 
			

with the first three lines going to standard error and the last line going to standard output. (Notice also that 7.6 is not an integer)

How To Submit

Please remember to use javadocs and RCS.

When you are confident that your program works correctly submit it using the following command:


try grd-232 lab4-1 SumArgs.java
				

Activity #2

For this activity you will write the code to open a file and search for occurrences of a specified string of characters. Your program must print out each line in which it finds the string. The string can exist anywhere on the line. The command line syntax is:


java FindString search-string file-name
			

The first thing that your program must do is check for the proper number of command line arguments. If this is not correct, display the following error on standard error and then terminate the program:


Usage: java FindString search-string file-name
			

Next the program must process the command line arguments. You will probably want to save the search string in a variable defined in your program. To read the data from the file you will need to construct the appropriate stream object and connect it to the file (remember this program is supposed to read character data).

The java.io, package-summary, package has two inheritance chains that can be used for dealing with files. One chain starts with the abstract classes InputStream and OutputStream, and the second chain starts with Reader and Writer. The Reader and Writer classes are defined for reading from character files. They provide facilities specific to character files, such as, reading a line of input. Use this hierarchy for your work in this activity and the next. As noted in the javadoc for BufferedReader it is advisable to use an object of this class over the lower level FileReader.

Using the file-name command line argument create a FileReader object that is attached to this file and wrap a BufferedReader object around the FileReader. You must handle any exceptions that are thrown by the constructor. If the file is not found, display the following error message on standard error and terminate the program:


ExceptionType occurred: detail-message
			

where ExceptionType is the type of exception you caught and detail-message is what is stored in the detailed message field of the exception object.

Your program must then enter a loop reading lines from the file and looking for search-string in the line (the Java String class contains a method that makes this easy to do). If search-string is found anywhere in the line, display the line on standard output. If you must catch any exceptions, handle them by displaying the following message to standard error and terminating the program:


ExceptionType occurred: detail-message
			

where ExceptionType is the type of exception you caught and detail-message is what is stored in the detailed message field of the exception object.

When you get to the end of the file, close the input stream and end the program.

How To Submit

Please remember to use javadocs and RCS.

Test your program using strings that are in the file and those that are not. Be sure to test the error conditions for the number of command line arguments and file open error. When you are sure that your program works correctly and you have provided correct javadocs, then submit it with the following command:


try grd-232 lab4-2 FindString.java
				

You can see the file that try will use when testing your program by clicking on Auxiliary/road.txt.

Activity #3

You will modify your program from the previous activity. Copy FindString.java to a new file FindString2.java. Rename the class FindString2 as well. Please remember to use javadocs and RCS.

In this activity you will add a third, optional command line argument. If a third argument is present, it will specify the name of an output file into which all the matching lines will be written. If the third argument is not present, the program must work exactly as before sending the matching lines to standard output. That means this version of the program must be able to write to either a file or the screen.

One way to write either to file or screen is to use if statements to select the appropriate output destination throughout the program. However, repeated code is cumbersome to maintain and obscures the logic of the program if overdone. Therefore you must not solve the problem this way.

The desired solution described next takes advantage of polymorphism in the Java I/O library. This approach uses overloaded constructors of the PrintWriter class to construct a PrintWriter object that is connected to the appropriate stream or writer for output.

Whether the program is working with a file or standard output, we want to use an object of type PrintWriter. You will be able to use the println() method in a PrintWriter object to generate output. Objects of the PrintWriter class can be constructed from either an OutputStream or a Writer object. This means that any object whose class is a subclass of either OutputStream or Writer can be used to construct a PrintWriter object. Since a BufferedWriter is a subclass of Writer you can construct a PrintWriter object using a BufferedWriter object, which will allow you to print() or println() to the output file.

The System.out object reference is a PrintStream object, which is a subclass of OutputStream. System.out can be used also to create a PrintWriter object.

Your submission for this activity will get no credit if you use conditionals to handle the print statements within the line processing loop of your program. There must be only ONE object that handles program output. That is, your program must use a single PrintWriter object for output and construct it in a manner appropriate for the current mode of program operation (this mode is based on the command line arguments).

Since the command line arguments to this program have changed from the prior activity, you must change the usage error message generated by the program. If the number of command line arguments is not correct, print the following message to standard error, and terminate the program:


Usage: java FindString2 search-string infile-name [ outfile-name ]
			

NOTE: Square brackets ( [] ) are commonly used in UNIX usage messages to surround optional arguments. the output file name is optional.

If the user specifies that the output from the program must be placed in a file, and an error occurs when the program opens the file or attempts to write to the file, your program must display the following message to standard error and terminate:


ExceptionType occurred: detail-message
			

where ExceptionType is the simple name of exception class caught and detail-message is the text stored in the message field of the exception object.

You must close the input and output streams before the program ends.

How To Submit

Please remember to use javadocs and RCS.

Again thoroughly test your program. Check that you have not broken any functionality that was working in activity 2. Make sure that the output file, if specified, is correctly written with the matching lines of text. Verify operation when the output file already exists but is write-protected. When you are sure that your program is working correctly, submit it using the following command:


try grd-232 lab4-3 FindString2.java
				


Grade Computation

Grade Breakdown: