08 - Exceptions and Files - Exercise
Overview
In this exercise we will read and write to a file in our file system. We will also practice handling exceptions, creating our own exception and unit test our code.
Task 1 - Create a new Employee
Locate and open the project from the last exercise -
EmployeeMavenProj
.Create a new class
EmployeeFileMain
for this task. Give it amain()
method.Define a static method in the same class - call it
getInput()
. This method will be responsible for interacting with the user. It should take oneString
parameter - a question to print out. It should read the answer from the terminal - declare and create anInputStreamReader
usingSystem.in
as its constructor parameter.InputStreamReader isr = new InputStreamReader(System.in);
Similarly, declare and create a
BufferedReader
using yourInputStreamReader
reference as its constructor argument. Use thereadLine()
method ofBufferedReader
to retrieve your keyboard input - that is theString
the method should return. ThereadLine()
method is declared to throw anIOException
. We have two choices - either we wrap the call to thereadLine()
method withintry
block and declare acatch
block, or we pass the buck. We will opt for the latter - declare yourgetInput()
method as throwingIOException
.Declare new
static
method: aninputEmployee()
method which will ask for a new employee's details to be entered. FrominputEmployee()
callgetInput()
three times - first ask for the first name and store the returned value in a variablenfame
. Secondly, ask for the last name - store the return value inlname
. Then ask for the age and store the returned value in variablestrAge
. Convert this value to anint
using static methodInteger.parseInt()
and store in the variable calledage
.Create an
Employee
object passing the three values into its constructor - you may need to create the constructor first!We need to handle the exception that may be thrown in the
getInput()
method. We will pass the buck again - declare yourinputEmployee()
method as throwingIOException
. Now it will need to be handled in themain
method - there is no other option.Within your
main
method, make a call toinputEmployee
method - you will see that it won't compile. The call needs to be withintry
block and we need to providecatch
block and capture theIOException
. Print out a message that something went wrong.try{ inputEmployee() }catch(IOException e){ System.out.println("Problem occurred.") }
Now run the application supplying the name and a numeric age.
Run the application again but supply non-numeric age -i.e.
abc
. The application with crash since it can't castabc
into anint
. You will see a stack trace fromNumberFormatException
.Let’s handle that exception. Declare the
inputEmployee
method as throwingNumberFormatException
, in themain
method include anothercatch
block to handle it. Make it printe.getMessage() + " is an invalid age!"
Run your application again and make sure it can handle non-numeric data.
Task 2 - Read from a File
Create another
static
methodshowEmployees()
. We will read from a.txt
file in this method.Create a new file in your project - call it
Employees.txt
. This file should NOT be a java class, just a simpleFile
. Fill it up - type in some sample dataWithin your
EmployeeFileMain.java
create a new variable to hold the path to this file. It should be a constant - the path is not going to change.Within your
showEmployees()
method declare and create aFileInputStream
with yourFILE_PATH
as a constructor argument. Declare and create aInputStreamReader
using yourFileInputStream
reference as its constructor argument. Declare and create aBufferedReader
using yourInputStreamReader
reference as its constructor argument.Create a
String
variable calleddata
and initialise it with an empty string. While the data is not null read a line from the file and print it out (hint:data = readLine()
).Call close on the BufferedReader when the loop exits.
There are a few points where exceptions may be thrown - we are going to pass the buck again and declare our showEmployees method as throwing
IOException
. That should cover all possibilities asFileNotFoundException
is a subclass ofIOException
.In
main()
method, we include the call toshowEmployees()
in try block and declare two catch blocks - one forIOException
and one forFileNotFoundException
. Which one should go first?You can comment out the call to the
inputEmployee
part.Run the application and check that you could see the content of your file printed into the terminal. Try to trigger
FileNotFoundException
- change your constant variable to a path that does not exist. Is it handled correctly?
Task 3 - Create your own exception
Create a new class called
UnderAgeException
. It should extendException
, have aprivate int age
variable, have apublic int getAge()
method to return the age and a constructor that receives anint
and aString
, storing the int as the instance variable age and passing theString
to the superclass constructor.Within the
inputEmployee()
method, after we cast the age toint
, check if the age is greater than 18. If it's not, throwUnderAgeException
passing the invalid age and a short message into the constructor. It will not compile, someone needs to handle this exception - addUnderAgeException
to the declaration of theinputEmployee()
method. We will handle it in themain()
.In the
main()
method, add a newcatch
block to theinputEmployee()
try
block. Handle the exception - print out that the employee's age is not valid.You can comment out the
showEmployee
method call.Run the application and check that the age is handled correctly.
Task 4 - Write into a file
Back in the
inputEmployee
method - add code to write the new employee's details into our file.Declare and create
FileOutputStream
passing theFILE_PATH
variable into tits constructor.Declare and create
OutputStreamWriter
passing the output stream into its constructor, last layer isBufferedWriter
that will take theOutputStreamWriter
.Call
write()
method on theBufferWriter
object. You'd want to write the employee's details into the file. Are there any suitable methods you can use on the employee object?Make sure you close the
BufferWriter
object.Run you application and check that the txt file has your data. Anything strange?
Hint: maybe use the
append()
method.
Task 5 - Unit test your code
The code we just created is not testable. Most of the methods return void and need user interaction. This is not a great situation for unit testing. We can refactor it though.
Create a new public static methods
createEmployee
. This will take threeString
parameters -firstName
,lastName
, and string version ofage
.This method should declare that it can throw
NumberFormatException
andUnderAgeException
.Copy and paste in the code that casts the string age into an int, the part that checks if the age is greater than 18 and the instantiation of the
Employee
object. It should return this object.Change your inputEmployee method to use the above method.
In the test package create a new file
EmployeeFileTest
. Focus on testing thecreateEmployee
method.Think about the test data - the
firstName
andlastName
are not important but theage
value can cause different exceptions to be triggered.Identify the test cases.
Create your tests.