Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Chapter 14: Exception Handling and Text I/O Run time error: A run-time error occurs when a program is running and it is given an instruction that is impossible for it to carry out. Some obvious examples are (1) Dividing by 0 (although Java allows division by 0 when using floats or doubles, but not integers). (2) Trying to open a file that doesn't exist or read past the end of an existing file. (3) Trying to convert a non-numeric string to a numeric value. (4) Trying to access an element of an array that doesn't exist (because the array index is either less than 0 or it is greater than or equal to the number of elements in the array). 14.2 Exception-Handling Overview Consider the following program (Listing 14.1): import java.util.Scanner; public class Quotient { public static void main(String[] args) { Scanner input = new Scanner(System.in); // Prompt the user to enter two integers System.out.print("Enter two integers: "); int number1 = input.nextInt(); int number2 = input.nextInt(); System.out.println(number1 + " / " + number2 + " is " + (number1 / number2)); } } Try to run it with the second integer equal to 0. The program blows up. There are two solutions to the problem. One solution is to protect the offending statement by putting it in an if statement (Listing 14.2). import java.util.Scanner; public class QuotientWithIf { public static void main(String[] args) { Scanner input = new Scanner(System.in); // Prompt the user to enter two integers System.out.print("Enter two integers: "); Document1 1 5/3/2017 int number1 = input.nextInt(); int number2 = input.nextInt(); if (number2 != 0) System.out.println(number1 + " / " + number2 + " is " + (number1 / number2)); else System.out.println("Divisor cannot be zero "); } } Yet another way is to exit the program when an error occurs (Listing 14.3). This is a bad way to handle the problem because it allows the method to decide to terminate the program, a decision that probably should be left to the main program: import java.util.Scanner; public class QuotientWithMethod { public static int quotient(int number1, int number2) { if (number2 == 0) { System.out.println("Divisor cannot be zero"); System.exit(1); } return number1 / number2; } public static void main(String[] args) { Scanner input = new Scanner(System.in); // Prompt the user to enter two integers System.out.print("Enter two integers: "); int number1 = input.nextInt(); int number2 = input.nextInt(); int result = quotient(number1, number2); System.out.println(number1 + " / " + number2 + " is " + result); } System.out.println("Execution continues ..."); } } Document1 2 5/3/2017 A better way is to do something called "throwing" an exception, and allowing the main program to decide what to do about it. import java.util.Scanner; public class QuotientWithException { public static int quotient(int number1, int number2) { if (number2 == 0) throw new ArithmeticException("Divisor cannot be zero"); return number1 / number2; } public static void main(String[] args) { Scanner input = new Scanner(System.in); // Prompt the user to enter two integers System.out.print("Enter two integers: "); int number1 = input.nextInt(); int number2 = input.nextInt(); try { int result = quotient(number1, number2); System.out.println(number1 + " / " + number2 + " is " + result); } catch (ArithmeticException ex) { System.out.println("Exception: an integer " + "cannot be divided by zero "); } System.out.println("Execution continues ..."); } } 14.3 Exception Handling Advantages Exceptions allow methods to avoid dealing with an error by passing it "up" to the caller (which can also pass it "up" to its caller, etc.). If it didn't work this way, then the exception would have to be handled where it occurs. The problem with this is that the method where the exception occurs may not know what to do to handle it! 14.6 The finally Clause If there is some code that you want to be executed whether an exception occurs or not, you can add a finally clause. try { Document1 3 5/3/2017 statements; } catch (Exception e) { handle the exception; } finally { final statements; } Common use: to make sure that a file gets closed, regardless of whether an error occurred or not. 14.7 When to Use Exceptions Only throw exceptions when you cannot handle the problem in the method where the exception occurred. Not this: try { System.out.println (refVar.toString()); } catch(NullPointerException ex) { System.out.println ("refVar is null"); } Use this instead: if (refVar != null) System.out.println (refVar.toString()); else System.out.println ("refVar is null"); Text Files: Using a Scanner object for input Reading an input file with multiple data items on each line. Let's create a program that will take text that has "tokens" on it (separated by white space): First name Middle initial Last name Score Document1 4 5/3/2017 And split the line into a name and a score. The easiest way to do this is to use the Scanner object, which splits a string into "tokens" delimited by white space (spaces, tabs, carriage returns). Code to read text strings and ints into an array of strings and ints Note that this can be done with a file using the same code except for the line that creates the new Scanner. public static void readStringsAndIntsFile() throws Exception { Scanner input = new Scanner("John T Smith 90 Eric K Jones 85"); String[] firstNname = new String[10]; String[] middleInitial = new String[10]; String[] lastName = new String[10]; int[] score = new int [10]; int i = 0; while (input.hasNext()) { firstName[i] = input.next(); middleInitial[i] = input.next(); lastName[i] = input.next(); score[i] = input.nextInt(); i++; } int lineCount = i; // Now print the array System.out.println ("\nNames and Scores"); for (i=0; i<lineCount; i++) System.out.println (String.format("%15s %1s %15s %5d", firstName[i], middleInitial[i], lastName[i], score[i])); } You can define your own delimiter character(s). Make the following changes: Scanner input = new Scanner("John/T/Smith/90/Eric/K/Jones/85"); // Put delimiter characters in square brackets input.useDelimiter("[/]"); You can check for multiple delimiter characters: Scanner input = new Scanner("John T/Smith^90 Eric/K^Jones/85"); // Put delimiter characters in square brackets: space, slash, and right bracket input.useDelimiter("[ /^]"); You can also use control characters (like tab, carriage return): Document1 5 5/3/2017 Scanner input = new Scanner("John T/Smith^90\nEric\tK\rJones/85"); // Put delimiter characters in square brackets: space, slash, caret, newline, tab, return input.useDelimiter("[ /^\n\t\r]"); Note that the above looks for exactly ONE of the delimiter characters. If there are two, then the scanner assumes that there are two tokens! So if you have two blanks separating two tokens, you MAY get an error. I have added an extra space before the word "Eric": Scanner input = new Scanner("John T/Smith^90 Eric/K^Jones/85"); // Put delimiter characters in square brackets input.useDelimiter("[ /^]"); This (above) generates an error only because we are now trying to read the word "Jones" into an array of integers! If we want to tell the scanner to treat multiple delimiters as a single delimiter (frequently there may be many spaces between tokens), we need to put a plus sign after the list of delimiters, like this: Scanner input = new Scanner( "John^T^Smith^^^^^^90 Eric\t \n\n\r K^Jones//////85"); // Put delimiter characters in square brackets input.useDelimiter("[ /^\t]+"); The "+" means "one or more of the preceding". Special characters in the argument to useDelimiter: [] anything in square brackets means "pick one" \t = tab \n = new line \r = carriage return + = one or more of the preceding Document1 6 5/3/2017 Text Files: Using a PrintWriter for output The textbook recommends using a File object and a PrintWriter object to write to a text file. Listing 14.13 public class WriteData { public static void main(String[] args) throws Exception { java.io.File file = new java.io.File("scores.txt"); if (file.exists()) { System.out.println("File already exists"); System.exit(0); } // Create a file java.io.PrintWriter output = new java.io.PrintWriter(file); // Write formatted output to the file output.print("John T Smith "); output.println(90); output.print("Eric K Jones "); output.println(85); // Close the file output.close(); } } Document1 7 5/3/2017