Introduction

Earlier in this lesson we have discussed a simple phone book program using a text file to store phone number entries. In this exercise you are going to improve the phone book program by adding a few additional features.

Recall that the simple phone book program allows you to do only two things:

  • Add a new phone number
  • List current phone numbers

Now we want the phone book program to be extended so that it has the following additional features:

  • Do not allow duplicated entries in the phone book
  • Find a phone number entry by name
  • Delete a phone number entry by name

In this exercise you need to complete these additional features one by one for the extended phone book program. Here are the tasks in the exercise:

  • Checking for duplicated entry when a new phone number is added
  • Finding a phone number entry by name
  • Delete a phone number entry by name

Overview

Here is the code of the program: PhoneBookEntry.java and PhoneBook.java

The Data File

You can get the initial data file from here: phonebook.txt

The format of the data file phonebook.txt is slightly different to the one used by the simple phone book program given in the lesson.

In this exercise, each phone number entry is still stored as a separate line. However, the name and the phone number of one entry are separated by a colon, without a space. You can see the format of the phone book from the given phonebook.txt, as shown below:

CSO:2358-6333
FMO:2358-6421
FO:2358-6418
HRO:2358-6188
SAO:2358-0842

Adding a New Phone Number

The phone book program allows you to add a phone number to the phone book. However, you cannot add two entries of the same name. Here is what you see when you want to add a new phone number using an existing name: see image.

The display on the left shows the current numbers in the phone book and the display on the right is what you see when you try to add a duplicated entry to the phone book.

Listing Current Phone Numbers

This feature is almost the same as the simple phone book program. The minor difference is that each phone number entry is printed with the phone number properly aligned in the extended phone book program.

Finding a Phone Number by Name

This is a new feature in the extended phone book program. You can give a name to the program and the program will find and show the corresponding phone number entry on the screen, like this: see image.

The display on the left shows the current numbers in the phone book and the display on the right shows what you see when you find a number by providing an appropriate name.

Deleting a Phone Number by Name

This is also a new feature in the extended phone book program. You can now delete an existing phone number entry by providing the name of the entry to the program. For example, this is what you see in the program: see image.

Figure: see image.

The display on the left is the current phone numbers in the program. The middle display shows the request for deleting the phone entry with the name 'ITSC'. The corresponding phone entry is then deleted as shown in the display on the right.

The PhoneBookEntry Class

A new class PhoneBookEntry has been given to you. Objects created from this class are used to store the phone number entries inside the code. The objects can then be used to handle the printing of the phone number entries as well as reading the phone number entries from the text file. You don't need to change this class file in the exercise.

Task 1. Checking for Duplicated Entry

At the moment if you run the phone book program you will be able to add entries with the same name. If you look at the addNumber method you can see that it contains this code:

// Check whether the name already exists, if so,
// print a message and exit the method
if (exists(name)) {
System.out.println("Phone number entry already exists!");
return;
}

As you can see, we have already included the checking for duplicated name for you. Why doesn't it work then? It is because the exists method, which has been used in the above code, is empty.

Your task now is the finish the exists method so that the code inside the addNumber method works.

The exists Method

The exists method works like this. It reads the data file phonebook.txt line by line. While reading the lines, it checks whether the name in the entry is the same as the one you want to add from the addNumber method. If they are the same, the new phone number is a duplicated entry. In this situation, the exists method returns true to indicate that there is a duplicated entry in the phone book. If, after reading the entire phone book, you cannot find any entry using the same name, the exists method will return false to indicate that you can now add the new entry in the phone book.

Reading the Data File

You can read the data file phonebook.txt using a BufferedReader. We have already used similar code to read the file when we list the current phone numbers from the phone book. If you look at the code in the listNumbers method you will see the method first gets the BufferedReader and then uses the BufferedReader to read and print the phone number entries.

Here is the while loop used to read the text file in listNumbers:

// Read the content line-by-line and print it out
String line;
while ((line = reader.readLine()) != null) {
// Create a new phone book entry from the data line
PhoneBookEntry entry = new PhoneBookEntry(line);
// Print the phone book entry
entry.print();
System.out.println();
}

Inside the while loop the first line of code creates a PhoneBookEntry object from the line of text read from the file. The PhoneBookEntry object automatically extracts the name and phone number from the line of text. You can then start to use several helpful methods from the PhoneBookEntry object. For example, the listNumbers method uses the print method to output the phone number entry nicely on the screen.

However, in the exists method you don't need to print the phone number entries. What you need to do is to check whether the name in the entry is the same as the given name parameter, i.e. the name you want to add to the phone book. If they are the same, you will return true to indicate the phone number entry already exists. If none of the phone book entries matches the given name, you will return false.

To get the name of the phone number entry you can use the getName method of the PhoneBookEntry object. Be reminded that you will have to use the equals method to compare the name because it is a string value, i.e.:

if (entry.getName().equals(name)) {
...
}

After you have finished the exists method you will not be able to add duplicated entry in the phone book anymore.

Task 2. Finding a Phone Number by Name

In the second task you need to find a phone number by name. The user enters the name and the program prints the corresponding phone book entry. If the name does not exist the program will show an appropriate message.

You will do this task in the findNumberByName method. Inside the method, the code to get the name input is given, as shown below:

// Get the name
System.out.print("Please enter the name: ");
String name = scanner.next();

Using the name variable you will find the phone number entry from the data file. Again, we can borrow the idea from the listNumbers method. If we look at the code in the method, you will see that the listNumbers method reads the entire phone book and prints all the entries out on the screen. In this task you don't need to print all entries. You only need to print the entry which matches the entered name. That means you can use most of the code from the listNumbers method. The only place you need to change is to check the name of the entry before you print, like this:

if (entry.getName().equals(name)) {
...print the entry...
}

If the name of the entry is the entered name, you will first print the corresponding entry and then finish the method using a return statement, i.e.:

return;

If you finish reading the data file without finding the corresponding entry, you will need to print an appropriate message to show that the entry does not exist, like this: see image.

Task 3. Deleting a Phone Number by Name

In this task, you need to get the name entered by the user and then delete the corresponding entry in the phone book. This is more complicated than the first two tasks because the first two tasks involve reading of the data file only but this task requires writing as well.

You may think that you can use a single while loop to do both reading and writing, i.e. deleting the requested entry while going through the list of entries in the phone book. However, you cannot do that because we only have one data file. You cannot read from and write to the same file at the same time. So let's do it in two stages.

Reading the Phone Book

Since we only have one single file, you will need to read the phone book into a temporary storage, delete the appropriate entry and then save the data back to the same file. At this stage, you will read the phone book and store it into a temporary place. The temporary place that we are going to use is an array. You can find this code in the given deleteNumberByName method:

// Prepare an array to store the phone number entries
PhoneBookEntry[] entries = new PhoneBookEntry[100];

// Store the number of entries in the phone book
int numOfEntries = 0;

The above code creates an array of PhoneBookEntry. The array has a size of 100 because, in this exercise, we have assumed that the number of entries in the phone book will not exceed 100. The size of the array has been fixed at 100 so we need something to remember the actual number of entries in the phone book.

The numOfEntries variable is created for this purpose. It stores the actual number of entries in the phone book.

You will read the data file line by line. For each line in the file you will create a new PhoneBookEntry object and put the object in the entries array. You can again borrow the code we have used in the listNumbers method to do that. This time, again, you don't need to print the entry inside the while loop. You will need to store the phone book entry into the array using this code:

entries[numOfEntries] = entry;
numOfEntries++;

The first line of above code stores the PhoneBookEntry object into the array, using the position indicated by the value of numOfEntries. Initially the numOfEntries variable is 0. That means the first time the above code is run, the PhoneBookEntry object becomes the first item of the array. When you run it the second time, you should store the PhoneBookEntry object in the second position of the array. Therefore, each time after you store the object in the array you need to increase the numOfEntries variable by one, as shown in the second line of the above code. If you do this, the numOfEntries variable will keep track of the current item you want to store the object as well as the actual number of items you have stored so far.

You don't actually need to store all phone number entries into the entries array. Remember that the objective of this task is to delete one entry from the phone book, you can store all entries in the array, except the one which matches the name entered by the user. You can use an if statement to do this, as shown below:

if (!entry.getName().equals(name)) {
...Store the object in the array...
}

After this stage, the entries array should contain all phone number entries, except the one you want to delete.

Writing to the Phone Book

Now that the appropriate phone number entries have been stored in the temporary place, the entries array. You can save the entries back to the data file. You can use a BufferedWriter to do that.

You have learned that, to get a BufferedWriter, you can use the following line of code (assuming you have a correct Path object):

BufferedWriter writer = Files.newBufferedWriter(path, Charset.defaultCharset(), StandardOpenOption.APPEND);

However, you need to use a slightly different BufferedWriter this time. The BufferedWriter created by the above code will append any new content at the end of the file. In this task, you don't really append data to the end of the file because the entries array already has ALL the data. That means you need to remove the StandardOpenOption.APPEND parameter so that the BufferedWriter will erase the current content of the file before writing the new one.

If the BufferedWriter is ready, you can use a for loop to write the entries into the file. Reminded that the number of phone book entries is stored in the numOfEntries variable the for loop should run for that number of times. For each entry you need to write the content of the entry into the file using the following code, assuming entries[i] points to the current entry in the array inside the loop:

// Add a phone number entry in a line
writer.write(entries[i].toLine());
writer.newLine();

After you finish writing the content of the file, you need to close the BufferedWriter using the close method.

Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.