Lecture 5: Basic Exceptions and File I/O Tami Meredith.

52
CSCI1227 Computer Programming and Problem Solving Lecture 5: Basic Exceptions and File I/O Tami Meredith

Transcript of Lecture 5: Basic Exceptions and File I/O Tami Meredith.

Slide 1

CSCI1227Computer Programming andProblem Solving Lecture 5: Basic Exceptions and File I/O Tami MeredithOverviewADTsBasic ExceptionsText File I/OCreating ExceptionsThrowing Exceptions

Abstract Data TypesA Class that contains a self contained conceptHIDES (e.g., abstracts) how the data isStoredManipulatedProvides "interface" methods to do the manipulation, but how they work internally is not important to the method's callerSeparate the work of programming the concept (implementation) from using the concept in other parts of the programSupports modular programming, team programming, program decomposition (into simpler parts)Conceptsprivate keep this data/method hiddenpublic part of the interface, anyone can use thisstatic share this data/method among all instances of the classfinal this data won't change until we compile (re-build) the programInterfacesConstructor: A method used to build/set-up a new instance of the objectHas the same name as the classHad no return typeCan take parameters which provide the initial values for the instance variablesADTs also provideAccessors: To access private (hidden) dataMutators: To change/set private dataMethods specialised for the datae.g., sum for math oriented data, compare for sortable data

An ADTpublic class date {

// Class Data private static final String[] cal = {"Jan", "Feb", "Mar", ... , "Dec" };

// HIDDEN Instance Data private int iDay, iMonth, iYear; private String sMonth; // Constructor public date (int d, int m, int y) { iDay = d; iMonth = m; iYear = y; sMonth = cal[iMonth-1]; }

// Mutators: Change values public void changeDate (int d, int m) { iDay = d; iMonth = m; sMonth = cal[iMonth-1]; } // Accessors Get values public int getDay() { return (iDay); } public String getMonth() { return (sMonth); }

// useful methods public boolean isLeapyear() { return ((iYear % 4) == 0); } public String format() { return(Integer.toString(iDay) + " " + sMOnth + " " +Integer.toString(iYear)); }} // end class dateUsing the ADTpublic class useADT { public static void main (String[] a) { date d1 = new date(16, 7, 2013); System.out.printf( "Today's date is %s.", d1.format()); if (d1.isLeapyear()) { System.out.println( "This date is in a leap year!"); } } // end main()} // end class useADTChoices: Implementation and InterfaceWe have:public boolean isLeapyear() { return ((iYear % 4) == 0); }

We could add: private boolean leap;and in the constructor : leap = ((iYear % 4) == 0);And thenpublic boolean isLeapyear() { return (leap);}Only ever calculate it once and store the result.

But then, why not:public boolean leap;And simply not bother with the accessor? (Like length in arrays).

ExerciseWrite an ADT called diceIt will have a random integer value (from 1 to 6) that is set in the constructorIt will have two interface methods:inspect: returns the current value roll: changes the value to a new random valueNote: The library class java.util.Random provides a method nextInt(n) that returns a value from 0 to n-1Solution/* Dice class by Tami Meredith, July 2013 */import java.util.Random;

public class dice {

private static final Random generator = new Random(); // class data private int value; // Instance data

// Constructor public dice() { this.roll(); }

// Interface methods public void roll () { value = 1 + generator.nextInt(6); } public int inspect () { return (value); }

} // end class diceOverloadingWhen two methods have the same name but different type signatures we say that the method is overloadedWe have seen this before with methods like sortint[] voidfloat[] void(int[], int, int) voidWe can do this for methods we write as well!At least one of the parameters must be different if we overload a methodOverloadingMethods must have unique signaturesThe number of parameters must differ , orThe type of at least one parameter must differReturn types can differ, but differences ONLY in return types is not permittedOverloading is applied before automatic type conversion (coercion)Overload resolution is the term we use for "deciding which method to use"ExerciseHere is the constructor from the date class public date (int d, int m, int y) { iDay = d; iMonth = m; iYear = y; sMonth = cal[iMonth-1]; }Overload the constructor so that a default date of January 1st is used if no day or month is specified.

Solutionpublic date (int y) { iYear = y; iDay = 1; iMonth = 1; sMonth = cal[0];}ExceptionsSometimes things go wrongAn "exception" is the Java term for an "error"In Java we "try" to execute/run some code to identify when something could go wrong and "throw" an exception to stop computation (and avoid the error)We then "catch" the exception to print an error message or (sometimes) attempt to fix the problemDetailsExceptions are an object that is, they are an instance of the class exceptionTry-Catch is a Java language element that alters control flowALL exceptions must be caught somewhereGenerally bad to try and fix things when an exception occurs since you often need to make assumptionsUsually we print an error message and exit the programAn exception is an ADT! Exceptions Syntaxtry block: Code to execute that could possibly throw an exceptionthrow statement: Code that creates an exception (not shown)catch block: Code to execute if an exception is thrownSyntax/Format:

try { // Do stuff here that could go wrong} catch (exception e) { // execution jumps to here when something goes wrong}Creating ExceptionsWe have not looked at library code that could go wrongIO with files has lots that can go wrongFile might not exist (wrong name)File might not be readable/writeable (permissions)Write might fail (disk full)Read might fail (empty file)To do file IO, we need to know how to handle exceptions since library methods can throw themExample: // Prepare to read input datapublic static Scanner openFile (String name) { File inputFile; try { // name might not be an existing, readable, file inputFile = new File (name); } catch (Exception e) { System.out.println(e.getMessage()); System.exit(0); } return (new Scanner (inputFile));} // end openFile()Example (Improved) // Generic Exception Handlerpublic static void handleException (Exception ex) { System.out.println(ex.getMessage()); System.exit(0);} // end handleException()

// Prepare to read input datapublic static Scanner openFile (String name) { File inputFile; try { inputFile = new File (name); } catch (Exception e) { handleException(e); } return (new Scanner (inputFile));} // end openFile()IO Frameworktry { /* * Try block * -- IO will go here */} catch (Exception e) { /* * Generic exception handler * -- can always use this as our catch block */ System.out.println(e.getMessage()); System.exit(0);}

File TypesTwo kinds of files: Text, BinaryIn text files, a numbers such as 12 is stored using two ASCII charactersIn binary files, the same number would be stored as00000000 00000000 00000000 00001100if it was a 32 bit integer (which looks like a form feed)Text files are readable, binary are notText files are longer, binary are usually shorterText files require data conversion, binary usually do notFocus on text files for now. Screen/Keyboard IOA user (via the keyboard and screen) is treated just like a binary file that can be read from (the keyboard) written to (the screen)We have seen most of the code to do binary file IO (text files are a tiny bit different)We use two ADTsScanner for readingPrintStream for writingAll characters printed by a PrintStream are converted into bytes (binary) using the platform's default character encodingThe PrintWriter class should be used in situations that require writing characters (text files) rather than bytes (binary files)System.out.print|ln|fSystem is a class that is automatically instantiated by the JVMIt is actually java.lang.Systemout is a static variable of type PrintStreambecause out is static, we use the class name to access this variableeverything in System is static so we don't need to know what the JVM calls the variableprint is the method we want to useprint is an instance method, and thus we need the name of the variable that stores the instance of PrintStream

ExerciseWrite a program to obtain an integer, n, and a String, s, from the user. Then print out the first n characters of s. You should prompt the user accordingly.Solution// Tami Meredith, July 2013import java.util.Scanner;public class prefix { public static void main (String[] args) { Scanner in = new Scanner (System.in); System.out.printf("Enter a string: "); String s = in.next(); int n; do { System.out.printf("Enter an integer [1-%d]: ", s.length()); n = in.nextInt(); } while ((n < 1) || (n > s.length())); System.out.printf("%s\n", s.substring(0,n)); } // end main()} // end class prefixFile IOTwo steps for inputOpen an input stream of type File (just like System.in)Apply a Scanner to break the stream into useful partsTwo steps for outputOpen an output stream Apply a PrintWriter to the stream (or a PrintStream just like System.out) so we can print to it

IO Framework (Text Files)File: board.datFile inStream = new File("board.dat")e.g.: System.inScanner input = new Scanner(inStream)PrintWriter output = new PrintWriter(outStream)e.g., like System.outFileOutputStream outStream = new FileOutputStream("board.dat", true);public static void main (String[] s) { ... }QuirksWe generally use a two step processOpen the IO streamApply a stream processorBut sometimes there are quirksSystem.in doesn't have a scanner even though we pretty much always need one and have to add itScreen output is binary and uses a PrintStream, files can use PrintStream (binary) or PrintWriter (text)Input (Text Files)We've mostly done this using the keyboard and its processor (e.g., System.in)With a file, all you need to do is:Select what file you wantOpen an input stream by creating a new streamAttach a new Scanner (processor)Use the output stream (with nextInt, nextLine etc.)If you don't close it, all streams are automatically closed for you when the program exits (which is why we never close System.in)File Input ExampleScanner input;String lineOfText;File filestream;

try { filestream = new File("input.txt"); input = new Scanner(filestream); lineOfText = input.nextLine(); input.close();} catch (Exception e) { System.out.println(e.getMessage()); System.exit(0);}OutputName the fileOpen a new FileOutputStreamCreate a PrintWriter to process the stream-- can combine 1, 2, and 3:PrintWriter fs = new PrintWriter(new FileOutputStream("thefile.txt",true));Write to it using println e.g., fs.println("hi");Close the stream when you are doneOutput An exampleString fileName = "output.txt";FileOutputStream filestream;PrintWriter outprocessor; try { // use false if we want replace not append filestream = new FileOutputStream(filename, true); outprocessor = new PrintWriter(filestream); outprocessor.println("Appended data in my file.");} catch (Exception e) { System.out.println(e.getMessage()); System.exit(0);}outprocessor.println("More appended data in my file.");outprocessor.close();Reading FilesWhen we read files, we often put the data into an arrayHow big should the array be?Read the file twice first time we count the items, then we create the array using the count, then we read it a second time into the array (never fails, very inefficient)Find a library method that will obtain the file size (fails though if size has no relationship to the number of items in the file)Create an array which we know is going to be big enough (may waste space in the array)Create a modest size array, read data until its filled, make a larger copy, and repeat until the data is readStore an extra value at the beginning of the file which indicates how many lines of data the file has must be changed every time the file is changedThe class FileA set of methods for checking a file's propertiesDoes not fully support reading or writingFile f = new File("/data/good.txt");int l = f.length(); // Number of bytesString s = f.getName(); // s = "good.txt"Also (See Figure 10.4)f.canRead(), f.canWrite(), f.exists(), etc.Output Made SimpleIn our class date we had:public String format() { return(Integer.toString(iDay)+" "+sMOnth+" "+Integer.toString(iYear));}Instead, we really needed:public String toString() { return(Integer.toString(iDay)+" "+sMOnth+" "+Integer.toString(iYear));}Since print|ln|f all use toString when doing coercions on non-string dataIn:System.out.println("The date is " + d);e.g., d.toString() is actually called for us!

Define toString() for every ADT/class you write!

ExerciseWrite a method called mysort that takes as its parameter an array of doubles and returns a sorted copy of the array.

Solutionpublic static double[] mysort (double[] in) { double[] out = new double[in.length]; for (int i = 0; i < in.length; i++) out[i] = in[i]; Arrays.sort(out); return (out);}ADTs: Interface MethodsConstructor (s) for instances of the classMutators to modify the instance dataAccessors to read/retrieve instance dataCopy Methods to make a new copytoString() so it can be easily printedequals() so deep equality can be checkedcompareTo() so that instances can be ordered and sortedA "Copy Constructor"We can overload the constructor to use when copying an object (an instance)public date (date original) { this.iYear = original.iYear; this.iMonth = original.iMonth; this.iDay = original.iDay; this.sMonth = original.sMonth;}

Then we can use the overloaded constructor to do a copydate d1 = new date (16, 7, 2013);date d2 = new date (d1);ExceptionsExceptions are objectsThey are instances of class ExceptionThey have a private String instance variableThe instance variable is set using the constructorThe instance variable is obtained using the accessor method getmessage()The variable holds a description of the error that occurredSomething Simpledouble decimal;int numer = input.nextInt();int denom = input.nextInt();if (denom == 0) { System.out.println("Div by zero"): decimal = 0.0;} else { decimal = numer / denom.}Throwing An Exceptiondouble decimal;int numer = input.nextInt();int denom = input.nextInt();try { if (denom == 0) throw new Exception("Div by zero"); decimal = numer / denom.} catch (Exception e) { System.out.println(e.getmessage()); decimal = 0.0;}

Playing Ball:Separating the catch and the throwpublic double divide (int n, int d) throws Exception { if (d == 0) throw new Exception("Div by zero"); return (((double) n) / ((double) d)));}... elsewhere ...

double decimal;int numer = input.nextInt();int denom = input.nextInt();

try { decimal = divide (numer, denom);} catch (Exception e) { System.out.println(e.getmessage()); decimal = 0.0;}

Some RulesThe try block might not fully executeThe catch block only executes if a throw occurs in the try blockWhenever a throw happens, a jump is done to the "nearest" (in scope) catch block the rest of the method and anything in the try block is ignoredAnything that can cause a throw (without a catch) must declare it throws ExceptionIf the throw cannot escape the method, no declaration is neededWe can throw Exceptions!Bad inputTrying to index an empty stringArray bounds errorsArray not big enough for the dataDivision by zeroProblems with files (permissions, names, etc.)

Anytime anything abnormal occurs

ExerciseWrite a method called average that takes as its input an array of integers and returns the average of the array as a double. Throw an exception for any erroneous conditions.Solutionpublic static double average (int[] in) throws Exception { double sum = 0.0; if ((in == null) || (in.length == 0)) { throw new Exception ("Empty array"); } for (int i = 0; i < in.length; i++) { sum += (double) in[i]; } return (sum / (double) in.length);} // end average() StacksA key ADT for programmingAnalogy: A stack of platesAlso called: LIFOs (Last In, First Out) or FILOs (First In, Last Out)Have two basic operationsPush(value) put value on the stackPop(value) take the top value off the stackSometimes have a Peek() look at top valueAn Integer Stack ADTpublic class stack { private int tos; private int[] data; public stack (int size) { data = new int[size]; tos = 0; } public void push(int val) { data[tos++] = val; } public int pop () { return (data[--tos]); }} // end class stackStreams make code prettier...

To DoEnsure you fully understand all of Chapters 1-7 except for: Graphics Supplements, Enumerations (3.3, 6.6), Packages (6.7), Sorting and Searching Arrays (7.4)Read Chapter 9 on exceptions 9.2 and a lot of 9.3 won't make senseRead Chapter 10 on Text File IO 10.1 to 10.3, Don't worry about 10.4-5 on Binary files

Do Assignment 4 in the lab todayNO Lab on ThursdayMidterm is a week today (Tuesday, July 23)