Exceptions
Exceptions
If you are going to learn about I/O you need to know about exception handling. Exceptions are conditions that should not happen, ie exceptions to the expected situation. An example of an exception is where you attempt to read a file from a disk but find that the file does not exist. This can happen when the disk is removable and it has unexpectedly been removed. With many programming languages it is entirely up to the job of the programmer to write exception handling code, and as a result programmers sometimes forget about it.
Java tries to gently push you in the direction of always handling exception by ensuring that the methods in the key classes require you to handle the exceptions they are likely to throw. Of course you can handle the exceptions by simply ignoring them, but by the time you have put in code to ignore them, you may as well actually handle them properly.
They keywords for handling exceptions are try and catch. You might like to think of these as "try to do this task" and if there is an exception "catch the exception and do something about it". The try and catch keywords surround the code with curly braces, so you will often read about "try/catch blocks". Here is an example of the use of a try/catch block
try{ DataInputStream dis = new DataInputStream(System.in); is.readChar(); }catch(Exception e){ System.out.println(e.getMessage()); }
I have always found the format of the catch part easy to get wrong. Note that the type of the exception is encased in parenthesis and you have to make up a variable name for the exception you are catching. Within the following brackets you need to place the code that should be run if the exception occurs. In this case I have used the getMessage method of the Exception. This is a common way of sending out a meaningful message indicating what has happened. Typically this might be "File not found".
In this example I have only caught the great grandparent of all Exceptions, good programming practice suggests you should try to catch the specific exceptions that might happen, such as FileNotFound or whatever. As you learn more about I/O you will quickly become familiar with the most likely Exceptions that can occur.
Here is a complete program that will read in the text of its own code and send it to the console.
1. import java.io.*; 2. public class FileOut{ 3. public static void main(String argv[]){ 4. FileOut f = new FileOut(); 5. f.go(); 6. } 7. public void go(){ 8. try{ 9. FileReader fr=new FileReader("FileOut.java"); 10. int ch; 11. while((ch = fr.read())> -1){ 12. System.out.print((char) ch); 13. } 14. }catch (Exception e){ 15. System.out.println(e.getMessage()); 16. } 17. } 18. }
Note how on line 4 the program makes a call to new to create a reference to an instance of this class. Without creating an instance of itself a program cannot call any of its own methods. On the following line, line 5 it calls the go method to get things started.
The first line of the go() method is line 8 of the program which starts a try block. This is because we are about to run some code that might throw an exception
The second instance of the use of the new keyword occurs with the creation of a reference to an instance of the FileReader class. The FileReader class is available to the program because of the use of the import statement at the very start of the program.
import java.io.*;
The use of the import statement is a little like using a path statement in DOS. It doesn't actually include or import any code, it just says that if Java is looking for any classes it should look to see if it can find them in the packages stated in the import statements. At first the number of packages available in Java can seem to be a bit daunting, but they are divided up into quite sensible and predictable areas such as io, sql, and classes covering the various ways of manipulating graphics. Remembering the names of the methods that classes use is a bit more tricky.
Note how the instance of the FileReader class is fed the name of a file to read. This is known as a constructor parameter. Constructors are special methods that have the same name as the class itself. In this case we have used the version of the class constructor that takes a String value of the name of the file the class is going to manipulate.
On line 10 the program declares a variable with the name ch and a type of int. The following three lines loop around the instance of the FileReader class reading in characters and sending them to the console. The read method of the FileReader classes returns the value of each character unless it is at the end of the file, in which case it returns -1. A bit of a fudge is required to get at the values of each character because the read method of the FileReader class is an int, which is a signed 32 bit number. What we want to output is a char which is an unsigned 16 bit number. This conversion is performed by using what is known as a cast, ie the type of an item of data is forced into another type. This is done simply by putting parenthesis round the name of the datatype you want to convert to.
9. FileReader fr=new FileReader("FileOut.java"); 10. int ch; 11. while((ch = fr.read())> -1){ 12. System.out.print((char) ch); 13. }