Exercises:

1. Write a program that will write the Gettysburg address to a text file. Place each sentence on a separate line of the file.

Solution:
See the code in Gettysburg.java.

2. Modify the program in the previous exercise so that it reads the name of the file from the keyboard.

Solution:
See the code in Gettysburg2.java.

4. Write a program that will record the purchases made at a store. For each purchase, read from the keyboard an item’s name, its price, and the number bought. Compute the cost of the purchase (number bought times price), and write all this data to a text file. Also, display this information and the current total cost on the screen. After all items have been entered, write the total cost to both the screen and the file. Since we want to remember all purchases made, you should append new data to the end of the file.

Solution:
See the code in RecordASale.java.


5. Modify the class LapTimer, as described in Exercise 13 of the previous chapter, as follows:

• Add an attribute for a file stream to which we can write the times

• Add a constructor

LapTimer(n, person, fileName) for a race having n laps. The name of the person and the file to record the times are passed to the constructor as strings. The file should be opened and the name of the person should be written to the file. If the file cannot be opened, throw an exception.

Solution:
See the code in LapTimer.java.


6. Write a class TelephoneNumber that will hold a telephone number. An object of this class will have the attributes

• areaCode—a three-digit integer

• exchangeCode—a three-digit integer

• number—a four-digit integer

and the methods

• TelephoneNumber(aString)—a constructor that creates and returns a new

instance of its class, given a string in the form xxx-xxx-xxxx or, if the area code is missing, xxx-xxxx. Throw an exception if the format is not valid. Hint: To simplify the constructor, you can replace each hyphen in the telephone number with a blank. To accept a telephone number containing hyphens, you could process the string one character at a time or learn how to use Scanner to read words separated by a character—such as a hyphen—other than whitespace.

• toString—returns a string in either of the two formats shown previously for the constructor.

Using a text editor, create a text file of several telephone numbers, using the two formats described previously. Write a program that reads this file, displays the data on the screen, and creates an array whose base type is TelephoneNumber. Allow the user to either add or delete one telephone number. Write the modified data on the text file, replacing its original contents. Then read and display the numbers in

the modified file.

Solution:
See the code in InvalidTelephoneFormatException.java, TelephoneNumber.java, TelephoneProgram.java. Input is in numbers.txt


7. Write a class ContactInfo to store contact information for a person. It should have attributes for a person’s name, business phone, home phone, cell phone, email address, and home address. It should have a toString method that returns this data as a string, making appropriate replacements for any attributes that do not have values. It should have a constructor ContactInfo(aString) that creates and returns a new instance of the class, using data in the string aString. The constructor should use a format consistent with what the toString method produces. Using a text editor, create a text file of contact information, as described in the previous paragraph, for several people. Write a program that reads this file, displays

the data on the screen, and creates an array whose base type is ContactInfo. Allow the user to do one of the following: change some data in one contact, add a contact, or delete a contact. Finally, write over the file with the modified contacts.

Solution:
See the code in InvalidContactException.java, ContactInfo.java, ContactProgram.java. Input is in contacts.txt

8. Write a program that reads every line in a text file, removes the first word from each line, and then writes the resulting lines to a new text file.

Solution:
See the code in FirstWordRemover.java.


10. Write a program that will make a copy of a text file, line by line. Read the name of the existing file and the name of the new file—the copy—from the keyboard. Use the methods of the class File to test whether the original file exists and can be read. If not, display an error message and abort the program. Similarly, see whether the name of the new file already exists. If so, display a warning message and allow the user to either abort the program, overwrite the existing file, or enter a new name for the file.

Solution:
See the code in FileCopier.java.

11. Suppose you are given a text file that contains the names of people. Every name in the file consists of a first name and last name. Unfortunately, the programmer that created the file of names had a strange sense of humor and did not guarantee that each name was on a single line of the file. Read this file of names and write them to a new text file, one name per line. For example, if the input file contains

Bob Jones Fred

Charles Ed

Marston

Jeff

Williams

the output file should be

Bob Jones

Fred Charles

Ed Marston

Jeff Williams

Solution:
See the code in RecoverNames.java.


12. Suppose that you have a binary file that contains numbers whose type is either int or double. You don’t know the order of the numbers in the file, but their order is recorded in a string at the beginning of the file. The string is composed of the letters i (for int) and d (for double) in the order of the types of the subsequent numbers. The string is written using the method writeUTF. For example, the string "iddiiddd" indicates that the file contains eight values, as follows: one integer, followed by two doubles, followed by two integers, followed by three doubles. Read this binary file and create a new text file of the values, written one to a line.

Solution:
See the code in UTFBinaryFileReader.java. The code in UTFBinaryFileWriter allows one to create a file with the appropriate format.

13. Suppose that we want to store digitized audio information in a binary file. An audio signal typically does not change much from one sample to the next. In this case, less memory is used if we record the change in the data values instead of the actual data values. We will use this idea in the following program. Write a program StoreSignal that will read positive integers, each of which must be within 127 of the previous integer, from the keyboard (or from a text file, if you prefer). Write the first integer to a binary file. For each subsequent integer, compute the difference between it and the integer before it, cast the difference to a byte, and write the result to the binary file. When a negative integer is encountered, stop writing the file.

Solution:
See the code in StoreSignal.java.

14. Write a program RecoverSignal that will read the binary file written by

StoreSignal, as described in the previous exercise. Display the integer values

that the data represents on the screen.

Solution:
See the code in RecoverSignal.java.

15. Even though a binary file is not a text file, it can contain embedded text. To find out if this is the case, write a program that will open a binary file and read it one byte at a time. Display the integer value of each byte as well as the character, if any, that it represents in ASCII.

Technical details: To convert a byte to a character, use the following code:

char[] charArray = Character.toChars(byteValue);

The argument byteValue of the method toChars is an int whose value equals

that of the byte read from the file. The character represented by the byte is

charArray[0]. Since an integer is four bytes, byteValue can represent four

ASCII characters. The method toChars tries to convert each of the four bytes to a character and places them into a char array. We are interested in just the character at index 0. If a byte in the file does not correspond to a character, the method will throw an IllegalArgumentException. If the exception is thrown, display only the byte value and continue on to the next byte.

Solution:
See the code in ByteReader.java.


Projects:

1. Write a program that searches a file of numbers and displays the largest number, the smallest number, and the average of all the numbers in the file. Do not assume that the numbers in the file are in any special order. Your program should obtain the file name from the user. Use either a text file or a binary file. For the text-file version, assume one number per line. For the binary-file version, use numbers of type double that are written using writeDouble.

Notes:
This project is deceptive: it requires more programs than the ones listed in the problem definition to process binary and text files containing floating point numbers; additional programs are required to create and view the data files. The solution shown here has separate programs to create and view data files, one for text and another for binary files. The program to process text files requires a method to translate the numbers from a String to type double. The easiest way is to use the wrapper class Double’s parseDouble method.
1)  Develop the class to create and view binary data files. Good models to follow are Doubler, Listing 10.8, for the overall program organization, and BinaryOutputDemo, Listing 10.5, for showing the file contents.
2)  Develop the class to process the data in a binary file (display the high, low and average), again using Doubler, Listing 10.8, as the model.
Use the programs from these two steps to develop similar programs for text files, but use TextFileOutputDemo, Listing 10.1, and TextFileInputDemo, Listing 10.2, as models for writing to and reading from text files.
References:
Listing 10.1, Listing 10.2, Listing 10.5, Listing 10.8
Solution:
See the code in WriteRealNumberBinaryFile.java, RealNumberHighLowAverageBinary.java, WriteRealNumberTextFile.java, and RealNumberHighLowAverageText.java.


2. Write a program that reads a file of numbers of type int and writes all the numbers to another file, but without any duplicate numbers. Assume that the numbers in the input file are already ordered from smallest to largest. After the program is run, the new file will contain all the numbers in the original file, but no number will appear more than once in the file. The numbers in the output file should also be sorted from smallest to largest. Your program should obtain both file names from the user. Use either a text file or a binary file. For the text-file version, assume one number per line. For the binary-file version, use numbers of type int that are written using writeInt.

Notes:
This project is similar to Project 1: data files need to be created before any processing can be done and it is easier to work with binary files than text. So a good approach is start with the binary file classes from Project 1 and modify them so data files can be created and displayed, then write the program to process the binary data files. Note that a separate program to display data files is necessary to view the files created by the program that removes the duplicates. If students do not have the programs from Project 1 to work from, then they could start with files from the text, BinaryOutputDemo.java (Listing 10.5) and Doubler.java (Listing 10.8). After all the binary file programs are written and tested, it is easier to develop the programs to create, read and process text files. Just as with Project 1, the code for setting up the input and output streams needs to be changed, the while-loop condition needs to be changed to end when a null string is read, and text Strings in the data file must be changed to ints by using the parseInt method in the Integer class
References:
Project 10.1, Listing 10.1, Listing 10.5, Listing 10.8
Solution:
See the code in WriteIntegerNumberBinaryFile.java, DisplayIntegerNumberBinaryFile.java, SortedIntegerNoDuplicatesBinaryFile.java, WriteIntegerNumberTextFile.java, DisplayIntegerNumberTextFile.java, and
SortedIntegerNoDuplicatesTextFile.java.


3. Write a program that checks a text file for several formatting and punctuation matters. The program asks for the names of both an input file and an output file. It then copies all the text from the input file to the output file, but with the following two changes: (1) Any string of two or more blank characters is replaced by a single blank; (2) all sentences start with an uppercase letter. All sentences after the first one begin after either a period, a question mark, or an exclamation mark that is followed by one or more whitespace characters.

Notes:
This project is deceptively simple. The problem statement is clear enough, with only a couple ambiguities to clarify. The solution shown here assumes that there is at least one line in the file to process and keeps all tabs and newlines unless they precede the first word on the first line. A helper method processes the first part of the first line to remove all leading white space and capitalize the first letter. After that, main simply reads one line of text at a time until it gets a null string, and uses another helper method to process the remaining text. This helper method is where most of the work is done: It processes each line, character by character, and uses flags to control the processing; to print only one space when there more than one in sequence, and to capitalize the first word in each sentence. Notice how the helper method to convert a character to upper case is written. The code first checks to see if the character is a lower case letter, and, if it is, it does integer arithmetic to convert the ASCII lower case code to the ASCII upper case code. A check of an ASCII chart will show that the upper case codes are 32 less than those for lower case. After doing the subtraction it is necessary to cast the integer result back to char to match the method’s return type, char.
References:
Project 10.1, Project 10.2
Solution:
See the code in WriteSentenceTextFile.java, DisplaySentenceTextFile.java, and EditSentenceTextFile.java.


4. Write a program similar to the one in Listing 10.10 that can write an arbitrary number of Species objects to a binary file. (Species appears in Listing 5.19 of Chapter 5.) Read the file name and the data for the objects from a text file that you create by using a text editor. Then write another program that can search a binary file created by your first program and show the user the data for any requested endangered species. The user gives the file name and then enters the name of the species. The program either displays all the data for that species or gives a message if that species is not in the file. Allow the user to either enter additional species’ names or quit.