Lab 6: File I/O¶
In this lab, you will implement a class that reads text from a file and instantiates objects based on its contents.
Learning Objectives¶
After completing this lab, you should be able to:
- Use
Scannerto read tokens from a file - Handle exceptions from file I/O operations using
tryandcatch - Use
ArrayListto store a dynamic number of objects - Iterate over an
ArrayListto search for a specific object
AI Assistance ✨
As usual, do not use AI tools to generate code solutions. However, you are encouraged to use them as a reference for syntax and method usage. But remember, you won't be able to use AI tools during exams, so make sure you understand the concepts and remember the key syntax!
We recommend using Microsoft Copilot Chat (free for all JMU students). You are free to use other AI tools if you prefer.
Getting Started¶
First, download the following files and put them in your cs159 folder, under src/labs/lab06 (you will need to create a lab06 folder):
- subset.txt
- all_courses.txt
- Course.java
- CourseCatalog.java (unfinished)
Part 1: Parsing the File¶
Open up your cs159 folder in VS Code, then navigate to and open the CourseCatalog.java file for editing.
Your task is to implement the loadFromFile method in the CourseCatalog class. This method should read course data from a file and create Course objects based on that data.
The file format is as follows:
<subject> <number> <credits> <course name>
For example:
CS 159 3 Advanced Programming
MATH 235 4 Calculus I
Note that the subject, number, and credits are separated by spaces, and the course name may contain spaces.
Scanner and File I/O¶
To read from a file, you will use the Scanner class along with the File class. Scanner works just like it does with System.in, but instead of reading from the console, it reads from a file.
-
Start by importing the necessary classes near the top of your
CourseCatalog.javafile, after the package declaration:import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; -
Next, in your
loadFromFilemethod, you will create aScannerobject that reads from the specified file. You will also need to handle the potentialFileNotFoundExceptionthat can be thrown if the file does not exist.-
Write the following two lines inside your
loadFromFilemethod:File file = new File(filename); Scanner input = new Scanner(file);
-
-
There should now be a red squiggly line under
new Scanner(file). This is because theScannerconstructor can throw aFileNotFoundException, which is a checked exception. You need to handle this exception using atry-catchblock.-
Put the two lines inside a
tryblock, and add acatchblock to handle the exception:try { File file = new File(filename); Scanner input = new Scanner(file); } catch (FileNotFoundException e) { System.out.println("File not found: " + filename); return; } -
What this means is that if the file is not found, the program will print an error message and exit the method early.
-
Reading the File¶
Now that you have a Scanner object that reads from the file, you can use it to read each line of the file, parse the course data, and create a new Course object to add to the list. So, if the file has 3 lines, you will need to create 3 Course objects and add them to the courses list.
-
You will want a
whileloop that continues as long as there are more lines to read.- Recall that
Scannerhas a method calledhasNextLine()that returnstrueif there is another line to read.
- Recall that
-
Inside the loop, you have two choices on how to parse each line:
- Use
Scannermethods to read each piece individually in this method.- Read the subject, course number, and credits first.
- Then, read the rest of the line (
nextLine()) as the course name.
- Better: Use
nextLine()to read the entire line as a string, then parse the string using anotherScanneror string methods.- Best: Organize your code by creating a private helper method called
parseLine(String line)that takes a line of text and returns aCourseobject. - Using a second
Scannerobject to parse the line may be easier than using string methods.
- Best: Organize your code by creating a private helper method called
- Use
-
Regardless of approach, for each line, you will need to:
- Read the course subject (
String). - Read the course number (
int). - Read the course credits (
int). - Read the course name (
String, may contain spaces).- Remember that
nextLine()returns the rest of a line, including spaces. - This may result in a leading space, which you can remove with
trim().
- Remember that
- Create a new
Courseobject using the data read above. - Add the
Courseobject to thecoursesArrayList.
AI: Quick Reference ✨
You can ask AI tools for quick reminders of Java syntax or methods. For example, you might ask:
"What is a private helper method in Java?""How can I use a Scanner to parse a String in Java?""How can I split a String by spaces in Java?"
Use these tools to help you remember syntax and methods, but do not ask them to write the full code for you. You might consider generating a reference sheet:
"Create a table of common Scanner methods in Java."
Remember, AI responses may not always be correct. Online references may be more helpful, such as w3schools Java Scanner Methods.
- Read the course subject (
-
Make sure to close the
Scannerobject at the end of thetryblock:input.close();- Why? It is good practice to close resources when you are done with them. This frees up system resources and lets other programs access the file.
-
Finally, implement the
toStringmethod to return aStringwith the "short" representation of all the courses, one per line. This will help you verify that the courses were loaded correctly.- The
toStringmethod of aCourseobject will return its short representation (e.g.,CS159 (3)).
- The
Test your implementation by running the main method in CourseCatalog. It should load the courses from subset.txt and print them out:
CS149 (3)
CS159 (3)
CS227 (3)
MATH231 (3)
MATH235 (4)
...
Part 2: Searching for a Course¶
Now, implement the remaining two methods in the CourseCatalog class:
findCourse(String subject, int number): This method should search thecourseslist for a course with the specified subject and number. If found, it should return theCourseobject; otherwise, it should returnnull.- Iterate over the
courseslist, and for each course, check if its subject and number match the specified values. - If a match is found, return that
Courseobject immediately. - If no match is found after checking all courses, return
null.
- Iterate over the
findAllCoursesWithCredits(int credits): This method should return anArrayListof all courses that have the specified number of credits.- You will need to create a new
ArrayList<Course>to store the matching courses. - Iterate over the
courseslist, and for each course that matches the specified credits, add it to the new list. - Finally, return the new list.
- You will need to create a new
Test your implementation by running the main method in CourseCatalog again. It should print out the results of the searches:
...
Found course: CS159 (3)
4 credit courses: [MATH235 (4)]
Test with the Full Dataset¶
Finally, test your program with the all_courses.txt file to ensure it can handle a larger dataset.
- In the
mainmethod, take a look at where the filename is specified.- Note the format of the path! It's relative to the
cs159folder. - Thus, it starts with
src/labs/lab06/.
- Note the format of the path! It's relative to the
- Change the filename from
subset.txttoall_courses.txt. - Instead of printing out the whole catalog, just print out the total number of courses loaded.
System.out.println(catalog.getCourseCount());
- Same with the 4 credit courses; just print out the number of them.
System.out.println(fourCreditCourses.size());
- Run the program again to see if it correctly loads and processes all the courses.
3330
Found course: CS159 (3)
4 credit courses: 112
Submission¶
Submit your completed CourseCatalog.java file to Gradescope.