Files & Streams cont..
Input File Exceptions
A FileNotFoundException is thrown if the file is not found when an attempt is made to open a file
Each read method throws IOException we still have to write a catch block for it
If a read goes beyond the end of the file an EOFException is thrown
Avoiding Common ObjectInputStream File Errors
There is no error message (or exception)
if you read the wrong data type!
Input files can contain a mix of data types it is up to the programmer to know their order and use the
correct read method
ObjectInputStream works with binary, not text files
As with an output file, close the input file when you are done with it
Common Methodsto Test for the End of an Input File
A common programming situation is to read data from an input file but not know how much data the file contains
In these situations you need to check for the end of the file
There are three common ways to test for the end of a file:1. Put a sentinel value at the end of the file and test for it.
2. Throw and catch an end-of-file exception.
3. Test for a special character that signals the end of the file (text files often have such a character).
The EOFException Class
Many (but not all) methods that read from a file throw an end-of-file exception (EOFException) when they try to read beyond the file
all the ObjectInputStream methods in Display 9.3 do throw it
The end-of-file exception can be used in an "infinite" (while(true)) loop that reads and processes data from the file
the loop terminates when an EOFException is thrown
The program is written to continue normally after the EOFException has been caught
Using EOFException
try { ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("numbers.dat")); int n; System.out.println("Reading ALL the integers"); System.out.println("in the file numbers.dat."); try { while (true) { n = inputStream.readInt(); System.out.println(n); } } catch(EOFException e) { System.out.println("End of reading from file."); } inputStream.close(); } catch(FileNotFoundException e) { System.out.println("Cannot find file numbers.dat."); } catch(IOException e) { System.out.println("Problem with input from file numbers.dat."); }
Chapter 9 6
main method fromEOFExceptionDemo
Intentional "infinite" loop to process data from input file
Note order of catch blocks:the most specific is first
and the most general last
Loop exits when end-of-file exception is thrown
Processing continues after EOFException: the input file is closed
Binary I/O of Class Objects
read and write class objects in binary file
class must be serializable
import java.io.*
implement Serializable interface
add implements Serializable to heading of class definition
methods used:
to write object to file:writeObject method in ObjectOutputStream
to read object from file: readObject method in ObjectInputStream
public class Species implements Serializable
outputStream = new ObjectOutputStream(
new FileOutputStream("species.records"));
...
Species oneRecord =
new Species("Calif. Condor, 27, 0.02);
...
outputStream.writeObject(oneRecord);
inputStream = new ObjectInputStream( new FileInputStream("species.records"));...Species readOne = null;...readOne = (Species)inputStream.readObject(oneRecord);
readObject returns a reference to type Object so it must be cast to Species before assigning to readOne
ClassIODemo Excerpts
The Serializable Interface
Java assigns a serial number to each object written out.
If the same object is written out more than once, after the first write only the serial number will be written.
When an object is read in more than once, then there will be more than one reference to the same object.
If a serializable class has class instance variables then they should also be serializable.
Why aren't all classes made serializable?
security issues: serial number system can make it easier for programmers to get access to object data
doesn't make sense in all cases, e.g., system-dependent data
SummaryPart 1
Text files contain strings of printable characters; they look intelligible to humans when opened in a text editor.
Binary files contain numbers or data in non-printable codes; they look unintelligible to humans when opened in a text editor.
Java can process both binary and text files, but binary files are more common when doing file I/O.
The class ObjectOutputStream is used to write output to a binary file.
SummaryPart 2
The class ObjectInputStream is used to read input from a binary file.
Always check for the end of the file when reading from a file. The way you check for end-of-file depends on the method you use to read from the file.
A file name can be read from the keyboard into a String variable and the variable used in place of a file name.
The class File has methods to test if a file exists and if it is read- and/or write-enabled.
Serializable class objects can be written to a binary file.
Reading Objects From FileWhy use files
Quickly load objects from file.Populate your system with data at runtime
Possible to incorporate into your projectLoad room types in at runtime.Load stored data in at runtime
public List<Vehicle> readVehicles(String file)
{
Scanner reader = new Scanner(file);
List<Vehicle> vehicles = new ArrayList<Vehicle>();
try
{
while (reader.hasNextLine())
{
vehicles.add(Vehicle.readFromScanner(reader));
}
}
finally
{
reader.close();
}
return vehicles;
}
Reading Objects from File// In vehicle Class
public Vehicle readFromScanner(Scanner scanner)
{
String make = reader.next();
String model = reader.next();
int year = reader.nextInt();
String vin = reader.next();
// Don't use double for currency values
BigDecimal value = reader.nextBigDecimal();
int milesDriven = reader.nextInt();
// Shouldn't this be some sort of date type?
Date lastOilChange = ??? //what do we do here???????
//Assuming the following constructor exists
return new Vehicle(make, model, year, vin, value, milesDriven,lastOilChange);
}
File would look as follows
Ford Fiesta 1990 ABCDE1234 5555.99 84000 2015/01/10
Toyota Avensis1999 DCADE1234 15555.99 14000 2015/11/10
What do we do about the date?
Read it as a String if you like and keep it as a string
OR have a Date field in your object, then we need to parse the date to string when saving or reading
Write date to filetry {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Date today = Calendar.getInstance().getTime();
String reportDate = df.format(today);
String dateToPrintToFile = reportDate;
File file = new File("testDate.txt");
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(dateToPrintToFile);
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
Read Date from File 2015/11/10 Date has been saved in previous example as String
We can read the date using reader.next() to get the next word
Read in the string and parse the string to a date using SimpleDateFormat
SimpleDateFormat sdf=new SimpleDateFormat("YYYY/MM/DD"); Date date=sdf.parse(reader.next()); MyObject.setDate(date);
Further ExampleDEBBIE STARR F 3 W 1000.00
JOAN JACOBUS F 9 W 925.00
DAVID RENN M 3 H 4.75
ALBERT CAHANA M 3 H 18.75
DOUGLAS SHEER M 5 W 250.00
SHARI BUCHMAN F 9 W 325.00
SARA JONES F 1 H 7.50
RICKY MOFSEN M 6 H 12.50
JEAN BRENNAN F 6 H 5.40
JAMIE MICHAELS F 8 W 150.00
ObjectList.txt
public class Payroll { private LineWriter lw; private PersonList list; private Person;
public Payroll(LineWriter lw) { this.lw = lw; } public void readfile() { try{ Scanner scanner = new Scanner(System.in); while(scanner.hasNextLine()) { String line = scanner.nextLine(); Scanner lineScanner = new Scanner(line); lineScanner.useDelimiter(" ");
person = new Person(); while(lineScanner.hasNext()) { person.setFirstName(lineScanner.next()); person.setLastName(lineScanner.next()); person.setGender(lineScanner.next()); person.setTenure(lineScanner.next()); person.setRate(Integer.parseInt(lineScanner.next())); person.setSalary(Double.parseDouble(lineScanner.next()));
list.add(person); } } }catch(FileNotFoundException e) {e.printStackTrace();} }
public class Person {
private String firstName, lastName, tenure; private char gender; private int rate; private double salary; public Person(){
} //settors . . . . . //gettors . . . . .
}
public class PersonList {
private ArrayList<Person> personList; public PersonList(){
personList = new ArrayList<Person>(); }
//list methods..//add//remove//search
}
Initialise the list
public class Driver{
public static void main(String args[]) { LineWriter lw = new LineWriter("ObjectList.txt"); Payroll payroll = new Payroll(lw);
payroll.readfile(); lw.close(); }
}
DEBUGGING
Overview
Testing and debugging are important activities in software development.
Techniques and tools are introduced.
Part of the material here comes from chapter 13 of Cohoon and Davidson’s book and chapter 6 of Barnes and Kolling’s book “Objects first with Java”.
Programming Errors Compilation errors
Syntax error (example: missing a semi-colon). Semantic error. (For example, applying modulus % on floating-
point value for certain programming languages. In Java ,is it fine? Yes!)
Easiest type of errors to fix. Runtime errors
Occur at runtime. Java’s exception mechanism can catch such errors.
Logic errors Program runs but produces incorrect result. Hard to characterize, hence hardest to fix.
Programming errors are also known as bugs Origin: a moth in the Mark I computer.
Testing and Debugging (1/7) Testing
To determine if a code contains errors. Debugging
To locate the error and fix it. Documentation
To improve maintainability of the code. Include sensible comments, good coding style and clear logic.
Testing
Yes
Error?
Debug
Testing and Debugging (2/7) Unit testing
Test of individual parts of an application – a single method, a single class, a group of classes, etc.
Positive versus negative testing Positive testing – testing of functionality that we expect to work. Negative testing – testing cases we expect to fail, and handle
these cases in some controlled way (example: catch handler for exception).
Test automation Regression testing – re-running tests that have previously been
passed whenever a change is made to the code. Write a test rig or a test harness.
This and the next slides involve materials not covered yet or to be covered in other modules (such as Software Engineering). You will need to gain relevant experience before you can appreciate them. Hence I will skip them for the moment.
Testing and Debugging (3/7) Modularization and interfaces
Problem is broken into sub-problems and each sub-problem is tackled separately – divide-and-conquer.
Such a process is called modularization. The modules are possibly implemented by different programmers,
hence the need for well-defined interfaces. The signature of a method (its return type, name and parameter
list) constitutes the interface. The body of the method (implementation) is hidden – abstraction.
Good documentation (example: comment to describe what the method does) aids in understanding.
static double
max(double a, double b) Returns the greater of two double values.
Testing and Debugging (4/7) Manual walkthroughs
Pencil-and-paper.Tracing the flow of control between
classes and objects.Verbal walkthroughs
Testing and Debugging (5/7) Print statements
Easy to add Provide information:
Which methods have been called The value of parameters The order in which methods have been called The values of local variables and fields at strategic points
Disadvantages Not practical to add print statements in every method Too many print statements lead to information overload Removal of print statements tedious
Testing and Debugging (6/7) Debugger
Provides Stepping (step and step-into) Breakpoint Tracking of every object’s state
Program testing can be used to show the presence of bugs, but never to show their absence. – Edgar Dijkstra
Testing and Debugging (7/7) Tips and techniques
Start off with a working algorithm Incremental coding/test early Simplify the problem Explain the bug to someone else Fix bugs as you find them Recognize common bugs (such as using ‘=’ instead of ‘==’, using
‘==’ instead of equals( ), dereferencing null, etc.) Recompile everything Test boundaries Test exceptional conditions Take a break
Turning Debugging Info On/Offpublic static int sum(int a, int b) {int left = 0;int right = data.length - 1;if (debugging) { System.out.println("sum called with a = " + a
+ " b = " + b);}int total = a + b;if (debugging) { System.out.println("total = " + total);}return total;
}
debugging = true;int ans = sum(3,5);
Debugging on.debugging = false;int ans = sum(3,5);
Debugging off.
Add an extra boolean debugging field to the class.
Testing Thoroughly (1/2) Recall our discussion last week. Richard couldn’t spot the
error in this code of his. // To find the maximum among 3 integer// values in variables num1, num2, num3.int max = 0;if (num1 > num2 && num1 > num3) max = num1;if (num2 > num1 && num2 > num3) max = num2;if (num3 > num1 && num3 > num2) max = num3;
He tested it on many sets of data: <3,5,9>, <12,1,6>, <2,7,4>, etc. and the program works for all these data.
But he didn’t test it with duplicate values! Eg: <3,3,3>, <7,2,7>, etc.
Testing Thoroughly (2/2) Richard wrote another program.
// To find the maximum among 3 integer// values in variables num1, num2, num3.int max = 0;if (num1 > max) max = num1;if (num2 > max) max = num2;if (num3 > max) max = num3;
He was told that the program doesn’t work but again he couldn’t figure out why. He has tested it on many data sets, including duplicate values!
Can you tell him what he missed out in his testing? Don’t forget the special cases!
Testing Boundaries It is important to test the boundary conditions.
Input Year Input Month
1582 2
1583 0
1583 13
1583 1
1583 12
final int CALENDAR_START = 1583;// validate input if ((year < CALENDAR_START) || (month < 1) || (month > 12)) {
System.output.println("Bad request: " + year + " " + month);}
Path Testing Paths: different routes that your program can take
Design test data to check all paths Example
if (x != 3) { y = 5;}else { z = z - x;}
if (z > 1) { z = z / x;}else { z = 0;}
if (x != 3)
y = 5 z = z - x
if (z > 1)
z = z / x z = 0
A
B
C
D
E
F
G
H
<x=0, z=1> Paths A, B, G, H.
<x=3, z=3> Paths E, F, C, D.
Integration and System Testing Integration testing is done as modules or components are
assembled. Attempts to ensure that pieces work together correctly Test interfaces between modules
System testing occurs when the whole system is put together
This comes in when you start to write bigger programs.
Debugger Using the debugger
Stepping Breakpoint Inspecting variables
I will illustrate in Lab
Top Related