HW7: File I/O¶
Learning Objectives¶
- Demonstrate understanding in reading from and writing to the file system (i.e., file input and output).
- Apply packages and develop unit testing.
Overview¶
In this assignment, you will apply your recently learned Java file I/O skills.
The Components to be Written¶
You must write the ProductFileProcessor
and CSVFileProcessor
classes perform input/output operations on
comma-separated-value (CSV) files. The relationship between these components
is illustrated in the following UML class diagram.
The ProductFileProcessor
Class¶
In HW6
, the Teethbrush
and ElectricTeethbrush
classes have been implemented.
The ProductFileProcessor
in HW7
is a utility class that can be used to
read/write Teethbrush
and ElectricTeethbrush
information from/to
the file system in (a simplified) comma-separated-valued (CSV) format
in which fields are delimited by a comma and there is a newline
character at the end of a record. For example, the CSV file for
an electric toothbrush might be as follows:
0,3,true,false,true
In addition to the specifications contained in the UML class diagram, this class must conform to the following specifications.
- The file name to use when reading and writing must be the model
name followed by
".bru"
. So, for example, the information about model"E1003"
must be in a file named"E1003.bru"
(in the working directory/folder). - All objects used for reading and writing must be closed when they are no longer needed.
- The
writeTeethbrush()
method must write theinventory
,hardness
, andpolished
attributes using"%d,%d,%b\n"
as the formatString
- The
writeElectricTeethbrush()
method must write theinventory
,hardness
,polished
,rechargeable
andultrasonic
attributes using"%d,%d,%b,%b,%b\n"
as the formatString
- The
readTeethbrush()
method must read a file written by thewriteTeethBrush()
method, construct and initialize aTeethbrush
object, and return it. - The
readElectricTeethbrush()
method must read a file written by thewriteElectricTeethBrush()
method, construct and initialize anElectricTeethbrush
object, and return it.
The CSVFileProcessor
Class¶
In addition to the specifications contained in the UML class diagram, this class must conform to the following specifications.
The read()
method must read all the records from the file passed to the constructor. The method assumes that it is passed in the format of line-oriented, comma-separated-valued (CSV) with the same number of elements as the number of records (lines) in the file.
The first line of the file contains an integer indicating the number of CSV data records (lines) to read. Any additional lines in the file are ignored.
For each record (line) in the file, the method reads and parses the CSV data. The read()
method returns a 2D array of strings, representing the extracted elements from the file.
The write()
method must take a 2D array of strings (representing records(lines) of CSV data) and write them to the file. The method should:
- Write the number of records(lines) (the length of the 2D array) as the first line in the file passed to the constructors.
- Follow that by writing each row from the 2D array as a comma-separated string, with each record written on a new line.
Example Input for write()
¶
String[][] data = {
{"p", "q", "r"},
{"s", "t", "u"},
{"v", "w", "x"}
};
Content of resulting CSV file:
3
p,q,r
s,t,u
v,w,x
Unit Testing¶
You must write JUnit tests for all of your classes. Your JUnit test
suite must cover all statements and all branches in all of the classes you write. Your tests must be in a
package named testing
and each test class must include the word "Test"
in its name.
To test the read methods in your classes you must create a JUnit test that first executes the appropriate write method and then executes the appropriate read method. (This is sometimes called round trip
testing of input/output.) Note that, to ensure that the write happens before the read, the two must be in the same JUnit test. You can (and should) have multiple tests of this kind, but each must be independent of the others.
Testing the read()
Method in CSVFileProcessor
¶
To test the read()
method which returned a 2D array, in the CSVFileProcessor
class, you are required to implement a helper method assertEquals2D
in CSVFileProcessorTest.java
. This helper method ensures a thorough comparison of two 2D arrays when testing the read() method.
The method should be declared as follows:
/**
* Asserts that two 2D string arrays are deeply equal.
*
* @param expected the expected array
* @param actual the actual array
*/
public static void assertEquals2D(String[][] expected, String[][] actual) {
// Add your code here
}
Implementation Requirements for assertEquals2D
¶
- Row Count Check: if the two arrays have different numbers of rows, use JUnit's
fail()
assertion with the message:Arrays have different number of rows
- Column Count Check: If any row in the arrays has a different number of columns, use
fail()
with the message:Arrays have different number of columns in row %d
, where%d
is replaced with the index of the row. - Value Comparison: If both arrays have the same dimensions, compare values cell by cell. Use JUnit
assertEquals
to assert the two arrays have same values at each cell. If a mismatch is found at position[i][j]
, the error message should beArrays differ at position [%d][%d]
, replacing%d
placeholders with the corresponding row and column indices.
Submission¶
You must submit (using Gradescope):
- Your implementations of the
ProductFileProcessor
andCSVFileProcessor
classes, and the corresponding JUnit test filesProductFileProcessorTest
andCSVFileProcessorTest
. - In addition to other tests,
CSVFileProcessorTest
must include theassertEquals2D
test.
Your grade will be reduced by 5 points for each submission after the 10th submission. So, you should try to ensure that your code is correct before you submit it the first time. In other words, you should not use Gradescope to check your style, to test your code, or to ensure that your tests cover your code - you should do all of that on your computer before you make any submissions to Gradescope.
Grading¶
Your code will first be graded by Gradescope and then by the Professor. The grade you receive from Gradescope is the maximum grade that you can receive on the assignment.
Gradescope Grading¶
Your code must compile (in Gradescope, this will be indicated in the section on "Does your code compile?") and all class names and method signatures must comply with the specifications (in Gradescope, this will be indicated in the section on "Do your class names, method signatures, etc. comply with the specifications?") for you to receive any points on this assignment. Gradescope will then grade your submission as follows:
Criterion | Points | Details |
---|---|---|
Conformance to the Style Guide | 0 | Success Required |
Passing Your Tests | 10 | All or Nothing; Success Required |
Coverage of Your Tests | 20 | Partial Credit Possible |
Correctness | 70 | Partial Credit Possible |
As discussed above, your grade will be reduced by 5 points for each submission after the 10th submission. Gradescope will provide you with hints, but may not completely identify the defects in your submission.
Recommended Process¶
Get Started¶
- Read and understand the entire assignment.
- Create a folder for this assignment named
hw7
. Then create packages (in thehw7
) namedio
andtesting
. - Ensure your code follows the provided style guide using available tools in VSCode.
Important: Package Declaration
The files should be placed in packages named io
or testsing
inside a directory named hw7
.
For example, you should have a directory structure like this in your VS code:
hws/
├── hw6/
│ └── product/
│ ├── ElectricTeethbrush.java
│ └── Teethbrush.java
├── hw7/
│ └── io/
│ ├── ProductFileProcessor.java
│ └── CSVFileProcessor.java
│ └── testing/
│ ├── ProductFileProcessorTest.java
│ └── CSVFileProcessorTest.java
Implement ProductFileProcessor
and CSVFileProcessor
classes¶
Since you will need to use Teethbrush
and ElectricTeethbrush
in ProductFileProcessor
class, you must first import them when you implement ProductFileProcessor
class.
Assuming that you have Teethbrush.java
and ElectricTeethbrush.java
in hw6
folder, you should be able to put following two lines before the class declaration in ProductFileProcessor
class:
import hws.hw6.product.Teethbrush;
import hws.hw6.product.ElectricTeethbrush;
If you do not have a completed Teethbrush.java
and ElectricTeethbrush.java
from hw6
, please contact your instructor.
Questions to Think About¶
You don't have to submit your answers to these questions, but you should try to answer them because they will help you determine whether or not you understand some of the important concepts covered in this assignment.
- The write() method in CSVFileProcessor writes a 2D array of strings to a file. Why is it important to first write the number of rows, and how does this help when reading the file back?