Java Chapter 11: Exceptions and Advanced File I/O
Handling Exceptions
- An exception is an object that is generated as the result of an error or an unexpected event. To prevent exceptions from crashing your program, you must write code that detects and handles them. - You can think of the code in the try block as being "protected" because the application will not halt if the try block throws an exception.
Retrieving the Default Error Message
- Each exception object has a method named getMessage that can be used to retrieve the default error message for the exception. - This is the same message that is displayed when the exception is not handled and the application halts. try { file = new File(fileName); 26 inputFile = new Scanner(file); 27 JOptionPane.showMessageDialog(null, 28 "The file was found."); 29 } 30 catch (FileNotFoundException e) 31 { 32 JOptionPane.showMessageDialog(null, e.getMessage()); 33 }
default exception handler
- If your code does not handle an exception when it is thrown, the default exception handler deals with it. - The default exception handler prints an error message and crashes the program.
Checked and Unchecked Exceptions
- In Java, there are two categories of exceptions: unchecked and checked. - Unchecked exceptions are those that inherit from the Error class or the RuntimeException class. So, you should not handle unchecked exceptions. - All of the remaining exceptions (that is, those that do not inherit from Error or RuntimeException) are checked exceptions.
Exception Classes
- an exception is an object. - all of the classes in the hierarchy inherit from the Throwable class. - Just below the Throwable class are the classes Error and Exception. - An EOFException object is thrown when an application attempts to read beyond the end of a file, and a FileNotFoundException object is thrown when an application tries to open a file that does not exist.
Binary Files
A file that contains raw binary data is known as a binary file. The content of a binary file is not formatted as text, and not meant to be opened in a text editor. - raw binary format.
Reading and Writing with the RandomAccessFile Class
A file that is opened or created with the RandomAccessFile class is treated as a binary file.
The Strack Trace
A stack trace is a list of all the methods in the call stack The call stack is an internal list of all the methods that are currently executing All exception objects have a printStackTrace method, inherited from the Throwable class, which can be used to print a stack trace.
exception handler
An exception handler is a section of code that gracefully responds to exceptions when they are thrown.
Handle each exception only once in a try statement
For example, the following try statement will cause the compiler to issue an error message because it handles a NumberFormatException object with two catch clauses
Serializing Aggregate objects
If a class implements the Serializable interface, then all of the fields in that class must be serializable This means that the object's class should also implement the Serializable interface. If it doesn't, then the transient key word should be used in the reference variable's declaration. private transient SomeClass refVar;
Object Serialization
Java allows you to serialize objects, which is a simpler way of saving objects to a file. When an object is serialized, it is converted into a series of bytes that contain the object's data. In order for an object to be serialized, its class must implement the Serializable interface The Serializable interface, which is in the java.io package, has no methods or fields To write a serialized object to a file, you use an ObjectOutputStream object. The ObjectOutputStream class is designed to perform the serialization process (converting an object to a series of bytes). FileOutputStream outStream = new FileOutputStream("Objects.dat"); ObjectOutputStream objectOutputFile = new ObjectOutputStream(outStream);
Appending Data to an existing binary file
The FileOutputStream constructor takes an optional second argument, which must be a boolean value. (true/false) true: If the argument is true, the file will not be erased if it already exists and new data will be written to the end of the file. false: If the argument is false, the file will be erased if it already exists. FileOutputStream fstream = new FileOutputStream("MyInfo.dat", true); DataOutputStream outputFile = new DataOutputStream(fstream);
The File Pointer
The RandomAccessFile class treats a file as a stream of bytes. The bytes are numbered, with the first byte being byte 0. The last byte's number is one less than the number of bytes in the file. The file pointer holds the byte number of a location in the file If the file pointer refers to a byte number that is beyond the end of the file, an EOFException is thrown when a read operation is performed To move the file pointer, you use the seek method. void seek(long position)
exception handling
The process of intercepting and responding to exceptions
Deserialization
The process of reading a serialized object's bytes and constructing an object from them is known as deserialization. To deserialize an object you use an ObjectInputStream object, along with a FileInputStream object. FileInputStream inStream = new FileInputStream("Objects.dat"); ObjectInputStream objectInputFile = new ObjectInputStream(inStream);
The finally clause
The try statement may have an optional finally clause, which must appear after all of the catch clauses. The finally block is one or more statements that are always executed after the try block has executed and after any catch blocks have executed if an exception was thrown. The statements in the finally block execute whether an exception occurs or not
Random File Access
To create and work with random access files in Java, you use the RandomAccessFile class, which is in the java.io package. RandomAccessFile(String filename, String mode) String mode: The two modes are "r" for reading, and "rw" for reading and writing. When a file is opened with "r" as the mode, the program can only read from the file. When a file is opened with "rw" as the mode, the program can read from the file and write to it. * Here are some important points to remember about the two modes: • If you open a file in "r" mode and the file does not exist, a FileNotFoundException will be thrown. • If you open a file in "r" mode and try to write to it, an IOException will be thrown. • If you open an existing file in "rw" mode, it will not be deleted. The file's existing contents will be preserved. • If you open a file in "rw" mode and the file does not exist, it will be created.
Creating your own exception classes
To meet the needs of a specific class or application, you can create your own exception classes by extending the Exception class or one of its subclasses. public class NegativeStartingBalance 8 extends Exception //Constructor public NegativeStartingBalance() 16 { 17 super("Error: Negative starting balance"); 18 } Program code public BankAccount(double startBalance) throws NegativeStartingBalance { if (startBalance < 0) throw new NegativeStartingBalance(startBalance); balance = startBalance; }
Reading data from a binary file
To open a binary file for input, you use the following classes: 1) FileInputStream 2) DataInputStream To open a binary file for input, you wrap a DataInputStream object around a FileInputStream object. FileInputStream fstream = new FileInputStream("MyInfo.dat"); DataInputStream inputFile = new DataInputStream(fstream); or DataInputStream inputFile = new DataInputStream(new FileInputStream("MyInfo.dat"));
Writing and Reading Strings
To write a string to a binary file you should use the DataOutputStream class's writeUTF method.
Writing data to a binary file
To write data to a binary file you must create objects from the following classes: 1) FileOutputStream 2) DataOutputStream You wrap a DataOutputStream object around a FileOutputStream object to write data to a binary file. The following code shows how a file named MyInfo.dat can be opened for binary output: FileOutputStream fstream = new FileOutputStream("MyInfo.dat"); DataOutputStream outputFile = new DataOutputStream(fstream); or DataOutputStream outputFile = new DataOutputStream(new FileOutputStream("MyInfo.dat"));
Polymorphic References to Exceptions
When handling exceptions, you can use a polymorphic reference as a parameter in the catch clause. For example, all of the exceptions that we have dealt with inherit from the Exception class. So, a catch clause that uses a parameter variable of the Exception type is capable of catching any exception that inherits from the Exception class try { number = Integer.parseInt(str); } catch (Exception e) { System.out.println("Conversion error: " + e.getMessage()); }
Using the @exception Tag in Documentation Comments
When writing the documentation comments for a method, you can document the exceptions thrown by the method by using an @exception tag. @exception ExceptionName Description Example: @exception NegativeStartingBalance When startBalance is negative.
Throwing Exceptions
You can write code that throws one of the standard Java exceptions, or an instance of a custom exception class that you have designed. -> throw new ExceptionType(MessageString); E.g. throw new Exception("Out of fuel"); - Don't confuse the throw statement with the throws clause. The throw statement causes an exception to be thrown. The throws clause informs the compiler that a method throws one or more exceptions.
Handling Multiple Exceptions with One catch Clause (Java 7)
catch(NumberFormatException | IOException ex) - The ability to catch multiple types of exceptions with a single catch clause is known as multi-catch
Handling an exception
try { (try block statements . . .) } catch (ExceptionType parameterName) { (catch block statements . . .) } - To handle an exception, you use a try statement - A try block is one or more statements that are executed and can potentially throw an exception.
Common Errors to Avoid
• Assuming that all statements inside a try block will execute. When an exception is thrown, the try block is exited immediately. This means that statements appearing in the try block after the offending statement will not be executed. • Getting the try, catch, and finally clauses out of order. In a try statement, the try clause must appear first, followed by all of the catch clauses, followed by the optional finally clause. • Writing two catch clauses that handle the same exception in the same try statement. You cannot have more than one catch clause per exception type in the same try statement. • When catching multiple exceptions that are related to one another through inheritance, listing the more general exceptions first. If you are handling multiple exceptions in the same try statement, and some of the exceptions are related to each other through inheritance, then you should handle the more specialized exception classes before the more general exception classes. Otherwise, an error will occur because the compiler thinks that you are handling the same exception more than once. • Forgetting to write a throws clause on a method that can throw a checked exception but does not handle the exception. If a method is capable of throwing a checked exception but does not handle the exception, it must have a throws clause in its header that specifies the exception. • Calling a method but not handling an exception that it might throw. You must either handle all of the checked exceptions that a method can throw, or list them in the calling method's throws clause. • In a custom exception class, forgetting to pass an error message to the superclass's constructor. If you do not pass an error message to the superclass's constructor, the exception object will have a null error message. • Serializing an object with members that are not serializable. If a class has fields that are objects of other classes, those classes must implement the Serializable interface in order to be serialized.