# Chapter 8

# Tying It All Together: Threads, Exceptions, and More

### CONTENTS

- Threads
  - Uses of Threads
  - Declaring Threads
  - new and the Instantiation of Threads
  - Destroying a Thread
  - Thread Methods
  - Named Threads
  - Synchronization of Threads
  - Summary of Threads
- Exceptions
  - Rationale for Java Exceptions
  - Exception Methods
  - An Example with try, catch, and finally
  - Using try in Exception Handling
  - Using catch in Exception Handling
  - Using finally in Exception Handling
  - Using throw in Exception Handling
  - The java.lang.Exception Class
  - Summary of Exceptions
- Streams
  - Data Flow with Java Streams
  - The Importance of Streams
  - Input Streams
  - Output Streams
  - Summary of Streams
- Summary

This chapter examines the final pieces of the Java programming language: threads, exceptions, and streams. Java uses these structures to create and control simultaneous activities and to perform error handling. These structures also perform interprocess communication among Java-controlled activities.

With threads, a single application in Java can easily run multiple concurrent code execution. This enables an application to do such powerful things as download a file, update a screen, and respond to user input all at the same time without the large amount of overhead incurred by the traditional fork used in languages such as C/C++.

Exceptions are Java's powerful and flexible method for handling errors, replacing the `return type error` code found in other languages. They are objects in Java and provide the same extensibility as any other object. Exceptions help to enforce Java's goal of being the safest language in which to program.

Streams are Java's way of communicating with the outside world. Streams enable a Java application to communicate with files, networks, devices, and other applications, and also allow for communication between threads within the same application. Streams are based on reading or writing a sequence of bytes from or to an outside source. Because the flow of data is a simple stream of bytes, specific knowledge of where the data comes from or is going to is not needed. This adds to Java's strength as a portable language.

There are several examples in this chapter that demonstrate these programming concepts. Try them yourself; you must see their output to appreciate and understand them. This is especially true because Java is not a procedural language, and it is difficult for most human minds to conceptualize nonsequentially. And you, the Java programmer-to-be, will have a lot more fun with Java when these powerful concepts are utilized.

These three structures are discussed in detail in the following sections. It is important to have a grasp of the uses of threads, exceptions, and streams to have powerful, pleasing Java applications and applets.

## Threads

Threads enable a single program to run multiple parts of itself at the same time. For example, one part of a program can display an animation on the screen while another part builds the next animation to be displayed.

For advanced programmers, threads are a lightweight version of a process. Threads are similar to processes in that they can be executed independently and simultaneously, but are different in that they do not have all the overhead that a process does.

The `fork` command is used to create a new process in C or C++. A forked process is an exact copy of the original process, with exact copies of variables, code, and so on. Making this complete copy of all of the parent process makes using the `fork` resource expensive. When they are running, the child processes are completely independent of the parent process inasmuch as they can modify data without any effect on the parent process.

Threads do not make copies of the entire parent process. Instead, only the code needed is run in parallel. This means that threads can be started quickly because they don't have all of the overhead of a complete process. They do, however, have complete access to all data of the parent process.

Threads can read and/or write data that any other thread can access. This makes interthread communication simpler, but can lead to multiple threads modifying data in an unpredictable manner. Additional programming care is required with threads.

### Uses of Threads

Threads are useful programming tools for two main reasons. First, they enable programs to do multiple things at one time. This is useful for such activities as letting a user do something while something else happens in the background.

Second, threads enable the programmer to concentrate on program functionality without worrying about the implementation of multitasking schemes. A programmer can simply spin off another thread for some background or parallel operation without being concerned about interprocess communications.

### Declaring Threads

To create classes that make use of threads, you can extend the class `Thread` or implement the interface `Runnable`. Both yield the same result. By implementing `Runnable`, existing classes can be converted to threads without having to change the classes on which they are based.

#### Creating Threads by Extending `Thread`

An example of creating a thread by extending class `Thread` follows:

> `public class MyMain {
> public static void main (String args[]) {
> CntThread cntThread; //declare thread
> cntThread = new CntThread(); //create thread
> cntThread.start(); //start thread running
> try {System.in.read();} //wait for keyboard input
> catch(java.io.IOException e){}
> cntThread.stop(); //stop thread
> }
> }
> `

> `class CntThread extends Thread {
> public void run() {
> int ix = 0;
> while (true) {
> System.out.println("running, ix = " + ix++); //write count to screen
> try {Thread.sleep(1000);} //sleep 1 second
> catch(InterruptedException e){}
> }
> }
> }
> `

Note
To exit the program, press Ctrl+C.

In this example, a thread is created that will write an incrementing counter to the screen. It will continue to count until the `main` routine receives a character from the keyboard, at which time the counting thread stops. This means you can press any key on the keyboard followed by the Enter key or press only the Enter key to stop the thread from counting.

This is an excellent example of the concept of threads because it introduces the keywords `try` and `catch` (discussed in the "Exceptions" section in this chapter) and also demonstrates the creation and termination of a thread.

#### Creating Threads by Implementing `Runnable`

The second way to create a thread is by implementing the `Runnable` interface. Like the previous example, the following code creates a thread that increments a counter until a character is entered from the keyboard:

> `import java.applet.*;
> import java.awt.*;
> public class MyApplet extends Applet implements Runnable {
> int ix = 0;
> Thread mainThread;
> CntThread cntThread;
> public void start() {
> if (mainThread == null) {
> mainThread = new Thread(this);
> mainThread.start(); //start main thread
> }
> }
> public void run() {
> cntThread = new CntThread(this); //create CntThread instance
> cntThread.start(); //start cntThread instance
> }
> public boolean keyDown(Event evt, int key) { //process key press
> cntThread.stop(); //stop cntThread instance
> return(true);
> }
> public void paint(Graphics g) {
> g.drawString("running, ix = " + ix, 10,20); //write count to screen
> }
> }
> class CntThread implements Runnable {
> MyApplet parent;
> boolean loop;
> Thread cntThread;
> public CntThread(MyApplet p) { //constructor for CntThread
> parent = p; //save parent instance
> }
> public void start() {
> if (cntThread == null) {
> cntThread = new Thread(this); //create counting thread
> cntThread.start(); //start counting thread
> }
> }
> public void stop() {
> loop = false; //set value to exit main while loop
> }
> public void run() {
> loop = true;
> while (loop == true) {
> parent.ix++; //incremen t counter
> parent.repaint(); //repaint screen
> try {Thread.sleep(1000);} //sleep 1 second
> catch(InterruptedException e) {}
> }
> }
> }`

Before you can view the applet in the applet viewer or your browser, you need to create an HTML document, such as the following:

> `<HTML>
> <HEAD>
> <TITLE>Using the Runnable Interface</TITLE>
> </HEAD>
> <BODY>
> <APPLET CODE="MyApplet.class" WIDTH=400 HEIGHT=400>
> <EM><B>You need a Java enabled Browser to see this cool applet</B><EM>
> </APPLET>
> </BODY>
> </HTML>`

This example also uses `try` and `catch` for exceptions. Look at the `start` and `stop` sections of the code. Starting and stopping threads are covered in detail later in the "Thread Methods" section of this chapter.

### `new` and the Instantiation of Threads

Instances of threads are created using the standard `new` keyword. Arguments to `new` can either use the `Thread` class explicitly, as in

> `mainThread = new Thread(this);`

or specify a class that is a subclass of `Thread`, like this:

> `mainThread = new MyThreadClass();`

In the first example, the current instance, `this`, of an object is initialized as a thread. Any object, however, can be passed as an argument to the `Thread` class.

Note that the `Thread` class has few constructors. If additional constructor types are needed, creating a subclass of `Thread` with the needed constructors is quite useful. The second thread-creation example allows for these possibilities.

### Destroying a Thread

You can control the execution of a thread in several ways using the `stop`, `start`, and `destroy` methods. The object remains in existence as long as the object is referenced somewhere, even if `stop` is invoked.

It is not necessary to explicitly destroy the thread object. Java's garbage collector takes care of this detail. If it is necessary to give the garbage-collection process a helping hand, make sure all references are removed to the thread object. The simplest way to do this is to assign the value `null` to all variables containing thread references, as in the following example:

> `Thread myThread = new Thread();
> myThread.start();
> myThread.stop();
> myThread = null;`

In this example, the thread object is instantiated with `new`. The thread is then started and stopped. Finally, `null` is assigned to the variable containing the thread instance. This last step ensures that Java's garbage collector will schedule a resource deallocation for that object.

### Thread Methods

All Java threads implement four methods: `init`, `run`, `start`, and `stop`. These are default methods in the `Thread` class; if a class implements `Runnable`, these methods must be declared explicitly.

#### `init`

The `init` method is called the first time a thread is started. It is usually used for initialization of objects, but can be used in any way the programmer sees fit. Here is an example of an `init` method:

> `public void init() {
> index = 0;
> }`

This method simply assigns a value of zero to the `index` variable. Larger, more complex applications might include code that opens databases, creates display objects, or just about anything that should be done only the first time a thread is started.

#### `start`

The `start` method is called to start a thread execution. This method usually contains the code for actually creating and starting a thread. Here is an example of a `start` method:

> `public void start() {
> if (mainThread == null) {
> new mainThread = Thread(this);
> mainThread.start();
> }
> }`

This method checks to see if a thread has not yet been created by testing whether the thread object `mainThread` is null. If it is not, a new thread object is created using `new,` and then the thread itself is started by calling the object's `start` method.

#### `stop`

The `stop` method contains the code needed to stop a thread's execution, often in the form of generating a signal that will be caught by all threads and that causes them to exit. `stop` also can change an object that causes a calling loop in the `run` method to exit. Here is an example of a `stop` method:

> `public void stop() {`

> loop = false; {

> `}`

This method simply sets a variable to `false`. `loop` is used in a main loop `run` method for control flow.

#### `run`

The `run` method is similar in function to `main` in C or C++. `run` contains the main body of code to be executed by a thread. Here is an example of a `run` method:

> `public void run() {`

> loop = true;

> while (loop == true) {

> System.out.println("index = " + index++);

> try {Thread.sleep(1000);}

> catch(InterruptedException e){}

> }

> `}`

The body of this method consists of the initialization of the `loop` variable and a `while` loop that will continue executing until `loop` no longer has a value of `true`. The body of the loop prints out the value of the `index` variable to the screen and then sleeps for one second.

This method can be combined with the example from `stop` to control processing.

### Named Threads

Java provides a means for assigning names to threads. Names can consist of any valid Java string. Naming threads makes it convenient to distinguish one thread from another and enables a parent process to query a thread for its name. A thread can be assigned a name at creation time or at any point thereafter. Threads can also be renamed at any time.

To assign a thread a name at creation time, simply use a `Thread` constructor that accepts a string as an additional argument, like this:

> `Thread myThread = new Thread(this."My first named thread");`

In this example, the thread is instantiated by `new` and assigned a name of `"My first named thread"`.

#### The `getName` Method

You can query a thread for its name using the `getName` method. `getName` returns the name associated with a specified thread object, as in the following example:

> `System.out.println("The name of this thread is " + myThread.getName());`

This example prints out the name assigned to the thread object `myThread`. Using the previous example, this statement would print the following to the screen:

> `The name of this thread is My first named thread`

A thread can also query for its own name in the same way:

> `System.out.println("My name is " + this.getName());`

#### The `setName` Method

You can set or change a thread name after creation using the `setName` method. The parent process, the thread itself, or any other method that has access to the thread object can do this. Following is an example of changing a thread name using `setName`:

> `myThread.setName("My newly renamed first thread");`

This example changes the name of the thread from `"My first named thread"` to `"My newly renamed first thread"`.

### Synchronization of Threads

Multiple threads can access the same object or method because threads are not independent processes with complete copies of data objects. However, there is no guarantee which thread will access an object at a given time, which can lead to unpredictable results. In situations when this is not acceptable, use the Java synchronization logic. The keyword that provides this logic is `synchronized`.

#### The `synchronized` Keyword

The `synchronized` keyword is used to lock an object long enough to execute a block of code. No other thread can make changes to the specified object while the block of code is being executed. Here is an example using `synchronized`:

> `public void printIndex() {`

> syncronized(index) {

> index++;

> System.out.println("index = " + index);

> }

> `}`

In this example, the `printIndex` method contains a synchronized block of code. In this block, the object `index` is locked while the block of code making up the body of the `synchronized` statement is executed. The increment of `index` and the printing of the value of `index` are contained inside the block. This ensures that the value of `index` is printed to the screen without having to worry that some other thread incremented `index` before it was printed.

`synchronized` also can be used as a modifier for methods, thus ensuring that only one thread at a time executes the method. The previous example could be rewritten using this construct as

> `public syncronized void printIndex() {`

> index++;

> System.out.println("index = " + index);

> `}`

### Summary of Threads

Threads are Java's way of running multiple, parallel code segments simultaneously. They are a lightweight process that does not have all the overhead that a normal process has. Threads do not make complete new copies of variables in the way that the C/C++ `fork` command does, allowing for faster thread startup. It also means that threads have access to each other's data. This can make communication among threads easier, but synchronization of data access may be a problem.

Threads are based on the class `Thread` and can be implemented by either extending class `Thread` or using the interface `Runnable`. Using `Runnable`, you can add threading to existing classes.

All threads implement the `init`, `start`, `stop`, and `run` methods. You can explicitly define these in the code, or use the default methods that come with the `Thread` class. `init` is called the first time a thread is started, and it is a good place to put initialization code. `start` is called any time a thread is started. This is usually where thread initialization is done and the thread is actually started. `stop` is used to stop the execution of a thread and usually contains code that will terminate the main body of the thread. Finally, `run` is started by `start` and normally contains the body of the thread code.

The problem of multiple threads modifying the same variable can arise due to the structure of Java, which allows threads access to common variables. Also, the system is in control of scheduling the execution of threads, which may be a different schedule than the programmer had anticipated. You can control this situation by using `synchronized`. `synchronized` can be used on an object or on a method, and ensures that only one thread can execute a block of code at a given time.

## Exceptions

So far, this book has presented the means by which a programmer can generate code correctly in Java. Correct code is, after all, is a valid programming goal. However, none but the simplest programs is error free; for example, simply not allowing enough space in an array for all needed elements results in an error.

There are problems that are beyond program control, and therefore also beyond the programmer's control. These include problems such as running out of memory. Other nonprogrammatic problems are the network being down or a hardware failure.

There are two main classes of problems in Java: errors and exceptions. Errors are caused by problems in Java itself and are generally of too detailed a nature for the program itself to solve. When an error is encountered, Java typically generates an error message to the screen and aborts the program.

### Rationale for Java Exceptions

Java handles potentially recoverable errors through exceptions, a special object class that handles virtually all errors in Java. Java continues the idea of making code as reusable and error-free as possible by treating errors as objects. Exception-handling code resides in the `java.lang` package and is automatically included in all compiled code.

The reason Java treats exceptions as objects is to be able to handle various errors using a standard extensible interface. This manner of treating exceptions confers all the standard advantages that object-oriented design provides, such as reusability and customization.

Exceptions can be handled in Java in several ways: In some cases they can simply be ignored; they can be handled directly by the code in which they occur; or they can be passed on to the code that called the method containing the occurrence of the exception in the hopes that it will be handled there.

If an exception is not handled explicitly anywhere in the code, it is passed on to the Java interpreter. The Java interpreter might handle it in some way or might simply exit. In the case of an applet within a browser, this may result in the browser dying. This is not a desirable activity, so exception handling within a program is generally recommended.

As mentioned previously, some exceptions in Java can be completely ignored. The Java compiler requires others to be handled in one fashion or another to get a clean compile. This latter case is the reason you have seen some exception handling in the examples shown in Chapters 6, "Fundamentals of the Java Language," and 7, "Building Objects," such as in the example of the `sleep` method. This method can generate an exception that Java requires to be handled explicitly.

You can customize existing exceptions or create new ones. Remember, all exceptions are located in class `java.lang.Exception`. To customize an existing exception, the program simply overrides the existing methods or rewrites the existing variables. To create a new exception, create a new class that extends `java.lang.Exception`.

### Exception Methods

Most Java exception handling is performed using the `try`, `catch`, `throw`, and `finally` methods. Of course, these methods can be extended if some unusual circumstance requires it.

Java uses the `try`, `catch`, and `throw` keywords to do actual exception handling. They are conceptually similar to a `switch` statement; think of `try` like the `switch` statement in terms of exactly identifying the condition to be tested.

`catch` is used to specify the action that should be taken for a particular type of exception. It is similar to the `case` part of a `switch` statement. There can be several `catch` statements in a row to deal with each of the exceptions that may be generated in the block specified by the `try` statement.

#### `throw`

Understanding exception handling in Java requires that you learn some new terminology. The first concept you need to grasp is that of throwing an exception, Java's name for causing an exception to be generated. For example, say a method was written to read a file. If the method could not read the file because the file did not exist, this would generate an `IOException`. In Java terminology, it is said that the method threw an `IOException`.

Think of it as a horse throwing a shoe: You must stop everything before real damage is done.

#### `catch`

The next term to learn in Java exception handling is `catch`. An exception catch is code that realizes the exception has occurred and deals with it appropriately. In Java terms, you say a thrown exception gets caught.

In the case of the `IOException` thrown because of the nonexistent file mentioned in the previous section, the `catch` statement writes an error message to the screen stating that the specified file does not exist. It then allows the user to try entering a different filename if the first was incorrect, or it may exit. In Java terminology, the `IOException` was caught.

#### `try`

`try` is the Java exception-handling term that means a Java program is going to try to execute a block of code that might generate (throw) an exception. The `try` is a way of telling the compiler that some attempt will be made to deal with at least some of the exceptions generated by the block of code.

#### `finally`

The `finally` statement is used to specify the action to take if none of the previous `catch` statements specifically deals with the situation. It is similar to the `default` part of a `switch` statement. `finally` is the big net that catches everything that falls out of the exception-handling statement.

### An Example with `try`, `catch`, and `finally`

The following example is the standard structure for Java exception handling, incorporating `try`, `catch`, and `finally`:

> `try {
> ` statement that generates an exception
> }
> catch (ExceptionType1 e) {
> process exception type 1
> }
> catch (ExceptionType2 e) {
> process exception type 2
> }
> finally {
> process all other exception types
> `}`

### Using `try` in Exception Handling

`try` is used to inform Java that a block of code may generate an exception and that some processing of that exception will be done immediately following the `try`. The syntax of `try` is

> `try statement;`

or

> `try {`

> statement(s)

> `}`

The keyword `try` begins the `try` construct and is followed by a statement or block containing the code that might generate an exception. This code could consist of several statements, one or more of which may generate an exception.

If any one statement generates an exception, the remaining statements in the block are skipped and execution continues with the first statement following the `try` construct, which must be a `catch` or `finally` statement. This is an important point to remember. It is an easy way to determine which block of code should be skipped if an error occurs. Here is an example:

> `public class MyMain {`

> public static void main (String args[]) {

> int[] myArray = new int[10];

> try {

> System.out.println("Before valid array assignment");

> myArray[0] = 1;

> System.out.println("Before invalid array assignment");

> myArray[100] = 1;

> System.out.println("After array exception");

> }

> }

> `}`

In this example, the array `myArray` is created with a length of 10. This is followed by a `try` statement that contains several statements. The first, third, and fifth statements simply write trace messages to the screen. The second statement contains a standard assignment statement that assigns the value `1` to array element `0`. The third statement also assigns an array, but attempts to assign a value of `1` to element `100` of the array. Because the array is only 10 in size, this generates an `ArrayIndexOutOfBounds` exception.

In tracing the execution of the block of code following the `try` statement, the first three statements are executed normally. The fourth statement, the invalid assignment, will start to execute and then generate an exception, which causes execution to continue at the end of the block, skipping the fifth statement.

A compilation error will result if you attempt to compile this code as it stands because any `try` statement must be followed immediately by one or more `catch` or `finally` statements. No other type of statement is allowed after the end of the `try` statement and before the first `catch` or `finally` statement. (`catch` statements are explained in the next section.)

### Using `catch` in Exception Handling

`catch` is used to handle a specific exception that has been generated in a `try` statement. The syntax is as follows:

> `catch (ExceptionType ExceptionObj) statement;`

or

> `catch (ExceptionType exceptionObj) {
> ` statement(s)
> `}`

The keyword `catch` begins the `catch` construct, followed by a parameter list that contains an exception type and an exception object. This in turn is followed by a statement or block containing the code used to process the exception.

Think of the `catch` construct as a method that will be called by the Java runtime interpreter if the particular exception type specified in the parameter list is generated. The object specified in the parameter list, exceptionObj, is a variable that contains the exception object generated and is local to the `catch` block. Within this block it can be manipulated as needed. The object must be assigned to a variable whose scope resides outside the block to use it outside the `catch` block, as in the following example:

> `public class MyMain {
> ` public static void main (String args[]) {
> int[] myArray = new int[10];
> try {
> System.out.println("Before valid array assignment");
> myArray[0] = 1;
> System.out.println("Before invalid array assignment");
> myArray[100] = 1;
> System.out.println("After array exception");
> }
> catch(ArrayIndexOutOfBoundsException e) {
> System.out.println("An array index error has occured");
> }
> }
> `}`

This example continues the earlier `try` example in the "Using `try` in Exception Handling" section. The required `catch` statement has been added after the `try` statement. This `catch` statement will catch the `ArrayIndexOutOfBoundsException` specifically. If any other exception occurs, this `catch` statement is ignored. In this case, an `ArrayIndexOutOfBoundsException` is generated, so the body of this `catch` statement will be executed. This body simply generates an error message to the screen. Execution continues normally with the first statement following the `catch` block that is not a `catch` or `finally` block.

Additional `catch` statements can follow the first `catch` statement. They must immediately follow the `try`/`catch` statement; otherwise a compilation error will occur. When an exception in a `try` statement is generated, the Java interpreter will treat all the `catch` statements following the `try` statement as cases in a `switch` statement. The first statement that is matched will be executed, and the remainder will be skipped. (An example of this is provided in the introduction to the "Exceptions" section of this chapter.)

Note that Java does not require any processing of the exception at all. Simply having a `catch` statement for an exception with an empty block is sufficient to avoid program abortion. This has been used in several examples in Chapters 6 and 7 with the `sleep` method.

`sleep` is used to put a process to sleep for a specified period of time, during which an `InterruptedException` could be generated. This could result from some other process signaling this process to continue or quit, for example. In the examples used in this book, catching this type of exception is considered unimportant, and no processing is required. However, because in most cases the compiler generates an error if the exception generated by `sleep` is not caught, an empty `catch` statement is used, as in the following:

> `try {Thread.sleep(timePeriod);}
> catch(InterruptedException e);`

As you can see, the `catch` statement simply ends in a semicolon (`;`), which does nothing. The result is an `InterruptedException` error that is caught and then totally ignored.

### Using `finally` in Exception Handling

`finally` is used to handle any exception generated within a `try` statement. The `catch` statement discussed previously can handle only one type of exception; the `finally` statement can handle any type of exception. Following is an example of the syntax:

> `finally statement;`

or

> `finally {
> ` statement(s)

> `}`

The keyword `finally` begins the `finally` construct, followed by a statement or block containing the code used to process the exception.

As with the `catch` statement, a `finally` block must follow immediately after a `try` or other `catch` statement or a compilation error results. A `finally` statement acts like a `default` case in a `switch` statement if it follows a series of `catch` statements. Anything that was not explicitly matched by an earlier `catch` statement is caught by the `finally` statement. A `finally` statement cannot be followed by another `catch` or `finally` statement or a compilation error will result. Because `finally` catches everything, additional statements would never be executed in any case. The following code fragment provides an example:

> `char readFile() {
> ` char ch = '\0';
> while (ch == '\0') {
> try {
> ch = myFile.read();
> }
> catch (EOFException e) {
> system.out.Println("End of file encountered");
> break;
> }
> catch (FileNotFoundException e) {
> promptUserForFileName(fileName);
> myFile = openFile(fileName);
> }
> finally() {
> system.out.Println("Unexpected error encountered while reading file");
> system.Exit(1);
> }
> }
> return(ch);
> `}`

In this example, a `while` loop is used to read a single character from a file. The first statement in the loop is a `try` statement that attempts to read a character from a file. It is followed by two `catch` statements that look for two specific exception types. A `finally` statement follows that catches all other types of errors. The loop itself is followed by a return of the character read.

Many types of errors can occur when reading a file, including `End of file`, `File not found`, `Access permission errors`, and others. The first `catch` statement handles `End of file` exceptions by simply exiting the loop, resulting in the return of a `null` character. The second `catch` statement handles `File not found` errors by prompting the user for a new or correct filename, opening the file, and then allowing the `while` loop to try again. Lastly, the `finally` statement catches all other errors. It writes an error message to the screen and then causes the application to exit.

### Using `throw` in Exception Handling

`throw` is used to cause the code itself to generate an exception. It is then up to calling routines to handle the exception. This is the preferred way of passing error information to calling routines in Java. The syntax follows:

> `throw(ExceptionObj);`

The keyword `throw` begins the `throw` construct, followed by a parameter list containing a single item. This item is an exception object, an object that has been declared to be of the desired exception type.

The exception type can be any of those predefined in Java or one custom designed for the job. Most exceptions can be found in `java.lang.Exception`. To design a new exception, extend the class `java.lang.Exception`. Here is an example:

> `public class MyMain {
> ` public static void main (String args[]) {
> MalformedURLException e;
> e = new MalformedURLException("Are you a novice? Get your URL's right!");
> throw(e);
> }
> `}`

In this example, an exception object (`e`) is declared. The object itself is then created with a standard `new` statement, in which the constructor allows replacing the standard error text for this exception. Finally, the exception object is thrown.

When an exception is thrown using the `throw` statement, current code execution stops. The exception is passed to the calling routine, and no other code is executed until the exception is caught somewhere. At that time, execution continues where the exception is caught. Keep this in mind when using the `throw` statement; it is usually a good idea to clean up as much as possible before throwing an exception. It is not a good idea to depend on the calling routines to clean up.

In some cases it may be desirable to catch a standard Java exception and then generate a customized exception by simply including a `throw` in a `catch` block, as in the following example:

> `public class MyMain {
> ` public static void main (String args[]) {
> int[] myArray = new int[10];
> try {
> myArray[100] = 1;
> }
> catch(ArrayIndexOutOfBoundsException e) {
> e = new ArrayIndexOutOfBoundsException("Please insure your array
> Âindex is within bounds.");
> throw(e);
> }
> }
> `}`

This is a modified version of the earlier `try` and `catch` examples. In this version, a customized error message is generated regarding the array index problem by reassigning `e` to a new exception object that includes the customized message and then using `throw` to throw another exception that must be caught at a higher level. If a `catch` or `finally` statement followed this `catch` statement, it would be ignored. However, if this `try` statement were itself enclosed in a different `try` statement, the execution would catch the exception. In other words, it is possible to catch a self-generated exception by putting a `throw` statement inside a `try` statement. This is rather like playing catch with yourself!

### The `java.lang.Exception` Class

Previously in the section titled "Exceptions," references were made to not only customizing existing exceptions, but creating new exceptions. These can be used to provide customized error codes for a particular application. Java does not provide a lot of numeric error-return codes as are found in other languages, so creating new exceptions falls right in with the Java philosophy.

Class `java.lang.Exception` is the superclass for all exceptions in Java. Creating your own extensions is simply a matter of extending this class just like extending any other class. For instance, to create a new exception called `MyOutOfRangeException`, the following implementation could be used:

> `public class MyOutOfRangeException extends Exception {
> ` public MyOutOfRangeException () {
> super();
> }
> public MyOutOfRangeException (String s) {
> super(s);
> }
> `}`

In this example, a new class called `MyOutOfRangeException` has been created by extending the `Exception` class. It contains two constructors. The first one calls the exception superclass constructor. This creates a new exception, but does not provide a way for the calling routing to customize the message. The second constructor is the same, but enables the calling routine to specify the error message associated with the exception.

To use this exception, simply declare a variable of type `MyOutOfRangeException`, initialize it with one of the two constructors, and then throw it, as in the following example:

> `public class VerifyRange {
> ` MyOutOfRangeException e;
> public void verifyIntRange (int value, int low, int high)
> Âthrows MyOutOfRangeException {
> if ((value < low) || (value > high)) {
> e = new MyOutOfRangeException("number " + value + " out of range");
> throw(e);
> }
> }
> `}`

In this example, a class called `VerifyRange`, to verify ranges of objects, has been created. The only method, `VerifyIntRange`, verifies that a value passed as an argument falls within the range also specified in the method's arguments. If the argument falls outside the range, a `MyOutOfRangeException` exception is created with `new` and then thrown with `throw`.

Notice that the method specifically declares that it throws this exception in the method declaration. Because of this, any calling routines are required to either provide an exception handler or explicitly declare that the method may pass on this exception. This would not be required if the `throw` portion of the declaration were left off. It is up to the programmer to determine whether an exception is important enough to require handling on the part of the calling routine.

### Summary of Exceptions

Exceptions are Java's way of performing error handling. They are used in many ways as a replacement for the more standard return codes used by languages such as C and C++. Java itself makes heavy use of exceptions for error conditions, and any programs should be ready to handle them. Using instructions makes a program more robust, which makes for a better program.

Exceptions are handled using a combination of three statement types: `try`, `catch`, and `finally`. `try` is used to inform the compiler that exception handling will be performed on an associated block of code. `catch` is used for processing a specific exception generated in the `try` block of code. Several `catch` statements can be specified sequentially to handle specific exceptions in a specific order. The `finally` statement can be used to catch all exceptions not specifically caught by a `catch` statement.

A program can generate its own exceptions using the `throw` statement. The exception itself can be either preexisting or newly created. Even a preexisting exception can be customized by specifying a different message when creating the exception object.

If you need a new exception, you can create one by simply extending an existing exception class such as `java.lang.Exception`. Exceptions are usually simple and can be created using only two constructors. Everything else is done by the superclass that the new exception extended.

Judicious use of exceptions make the difference between a program and a truly user-friendly, good program. Nothing is less user-friendly than an aborted program.

## Streams

You have probably noticed that the complexity of programming with Java has been slowly building in this book. The next subject is probably the most complex Java concept that must be mastered to complete your knowledge of Java: streams.

Streams in Java provide a way for two or more processes to send information to each other without any of the processes having to know anything about the others. This means that with streams you can write an application or applet that can then pass data to almost any other stream-based application or applet! It is even possible for multiple threads making up a single process to pass data to each other via streams.

### Data Flow with Java Streams

At the highest level, streams work by simply sending information from a producer process to a consumer process. A producer process generates data for use by another process. A consumer process makes use of data produced by another process. Information that leaves a producer process is known as an output stream. Information that arrives at a consumer is known as an input stream. The information that makes up a stream is simply a sequence of data blocks sent one at a time from the producer process to the consumer process. The blocks themselves can be almost anything, from simple bytes to complex objects. Only the primitive data types are directly supported in Java, but any object can be sent as a data block by creating new stream classes.

Streams are unidirectional-that is, the data for a particular stream travels only from the producer to the consumer. The consumer cannot send any data back to the producer on this same stream. However, there is nothing to prevent the consumer process from opening a different stream back to the producer process. In fact, a single process can have multiple streams that can be any combination of producers and consumers. These also can be opened between multiple other processes. This is one of the powerful attributes of streams.

Each stream has only a single producer and a single consumer. A single producer stream cannot feed multiple consumer streams, and a single consumer stream cannot be fed by multiple producer streams. This is not to say that a producer process could not feed multiple consumer processes; it's just that each consumer process must be fed by a different and unique stream. The same is true for a single consumer process that is fed by multiple producer processes.

Consumer processes do not have to blindly accept data from a producer, however. They can start and stop the flow of information, read as much or as little of a stream as desired, and in some cases even determine how much data is left in the stream. Consumer processes can also reset the stream to an earlier point. This control makes it sound like the consumer is communicating back to the producer process, but what is actually happening is that the consumer process is communicating with the Java internals that handle the stream.

If a consumer process pauses while receiving data from its end of the stream, the producer will not necessarily pause in sending data. The producer may continue to produce data, and the Java stream-handling code may buffer the data until the consumer process begins accepting data again. This is important to remember: the producer and consumer do not communicate directly with each other over a streams interface. Instead, the producer simply generates a stream of data at one end, which then goes into the Java stream-handling code. From there it is sent to the consumer. The producer and consumer have no knowledge of each other.

### The Importance of Streams

Streams have many uses in Java and, in fact, are used quite heavily within Java itself. They are used to read and write information to devices, files, databases, network sockets, other processes-almost anything. All stream interfaces implement a basic set of methods that the programmer can use. These methods are common across all stream types, which makes using a new stream type simple.

There are a few stream methods found in some Java package extensions, but the standard ones are found in the `java.io` package. This package must be imported in all applications or applets that make use of threads.

There are some extended stream methods that are not always implemented, such as the capability to reset the stream to an earlier point. For these cases, there are other methods discussed in the following sections that you can use to check whether extended methods are supported. This makes it possible for a program to take advantage of these methods if they are available.

So how do you implement a stream? Let's find out!

### Input Streams

Input streams are the data streams that are accepted and processed by a consumer process. As mentioned before, stream classes and their associated methods are found in the package `java.io`. Every application or applet that uses streams must explicitly import this package in the beginning of the code. You do this with a standard `import` statement:

> `import java.io.*;`

There are many different classes of input streams. Each has its own purpose and can, of course, be extended or customized as needed by the programmer. Table 8.1 is a complete list of Java's input stream classes.

Table 8.1. Input stream classes.

`BufferedInputStream` | Reads data from the buffer to minimize number of actual reads needed
`ByteArrayInputStream` | Reads byte data into an array of bytes
`DataInputStream` | Reads data objects from a stream rather than bytes like most other input streams
`FileInputStream` | Reads data from a file
`FilterInputStream` | Allows a stream to connect to subclasses of itself that can be used to filter the data
`InputStream` | Abstracts the superclass to all `InputStream` classes
`LineNumberInputStream` | Reads an input stream that uses line numbers
`PipedInputStream` | Reads data from a pipe connected to another process
`PushBackInputStream` | Allows pushing a single character back onto input stream
`SequenceInputStream` | Treats multiple sequential input streams as single input stream
`StringBufferInputStream` | Reads character data into an array of characters (a string)

The methods associated with input streams are of two types: those that are guaranteed to work with all input streams (see Table 8.2) and those that are not (see Table 8.3).

Table 8.2. Input stream methods guaranteed to work.

`read` | Reads data from an input stream
`skip` | Skips past data in an input stream
`markAvailable` | Tests if the `mark` method is available on this input stream
`close` | Closes an input stream

Table 8.3. Input stream methods not guaranteed to work.

`available` | Amount of data available in an input stream
`mark` | Marks a point in an input stream to which to return
`reset` | Returns to a specified point in an input stream

The methods not guaranteed to work either may not be available as valid methods or may return inaccurate or inconsistent results because of the uncertain nature of a producer. Some producers send a consistent stream of data; others will not produce data until the intervening Java stream-handling code indicates it is ready. For these reasons, the results can be unpredictable.

#### `read`

The `read` method is the most basic of the input stream methods. This is the method an application uses to read data from a stream. It has several variations, mainly involving how much data is read, where in the stream the data starts and stops, and to where the data is written. Which `read` method you use depends on your application's needs.

All `read` methods are based on a blocking read, meaning that when a `read` method is called, it will not return until all the data requested has been received or an exception occurs. Recall that in some earlier examples, a read of the keyboard was done. In these cases, the `read` function did not return until a character was entered on the keyboard. This is an example of a blocking read. If the equivalent of a non-blocking read is needed, methods exist for checking if data is available before a read is executed.

All read methods also throw the `IOException` exception. This must be handled in an application's code, either by using a `try`/`catch`/`finally` structure or by adding a `throws` statement to the class declaration. The syntax of `read` follows:

> `int read();
> ` int read(byte[] buffer);
> `int read(byte[] buffer, int offset, int length)`

The first form of `read` simply attempts to read a single byte from the input stream. The byte `read` is returned by the function itself, cast as an `int`. The second form reads data into a buffer, an array of bytes. It attempts to read enough data to fill the buffer. The last version also attempts to fill a buffer, but starts at the indicated `offset` into the stream and will read only `length` bytes. All cases of `read` return an integer, which is used to indicate the number of bytes actually read. If there is nothing more to be read, it returns a `-1`, as in the following:

> `import java.io.*;
> ` public class MyMain {
> public static void main (String args[]) {
> FileInputStream s; //declare s to be a file input stream
> int rcode; //declare a variable for the read return code
> try { //use try to catch file open exceptions
> s = new FileInputStream(args[0]); //open the input stream
> rcode = 0;
> while (rcode != -1) { //loop reading file until entire file is read
> try { //use try to catch IO exceptions
> rcode = s.read(); //read character from file
> System.out.println("ch = " + (char)rcode);//print char to screen
> }
> catch (IOException e) { //handle IO exceptions
> System.out.println("Unknown IO error reading file " + args[0]);
> System.exit(2);
> }
> }
> }
> catch (FileNotFoundException e) { //handle file not found exception
> System.out.println("File " + args[0] + " not found");
> System.exit(1);
> }
> }
> `}`

In this example, `read` is used to read bytes from a file input stream. The name of the file to read is passed as the first argument on the command line when you run the application. Therefore, if you wanted the program to read from a file called `sample.txt`, you would invoke the `MyMain` application using the following:

> `java MyMain sample.txt`

A stream object variable `s` is declared to be of type `FileInputStream`. It is then initialized by opening the file input stream using the `new` operator. This will result in the file actually being opened, so a `File not found` exception must be caught at this point if the file does not exist.

Next, a `while` loop is used to continuously read a single byte from the stream until the `read` method returns `-1`. The body of the `while` loop starts out by calling the `read` method to read a byte. `read` may return an `IOexception`, so it is also placed in a `try` statement. If the `read` succeeds, the byte is printed to the screen. If not, a `catch` statement writes an error and the application aborts.

This example shows the basics for handling a simple input stream. It shows how to open an input stream, read data from it, detect the end of it, and set up exception handling for both the `open` and the `read` of it.

#### `skip`

The `skip` method is used to bypass a fixed number of bytes of an input stream, thereby enabling the program to move quickly through the stream. It can be used to skip unneeded data or to move to a specific point in the stream. If used with a database input stream, it can be used to skip through a set of fixed-length records to get to the record needed. If used with a file input stream, it can provide some of the same functionality as the C/C++ `lseek` function.

The `skip` method works in a forward direction only. It cannot be used to skip backward to an earlier point in an input stream. Some input streams allow this functionality, but they use the `mark` and `reset` methods (covered later in their respective sections) to accomplish this.

The `skip` method throws the same `IOException` exception that `read` does. This must be handled in an application's code, either by using a `try`/`catch`/`finally` structure or by adding throws to the class declaration. The syntax of `skip` follows:

> `long skip(long num);`

The `skip` method accepts a single argument of type `long`: the number of bytes to skip in the input stream. Because data streams do not have any fixed size, if more bytes than can be handled in a `long` must be skipped, use multiple `skip` statements.

There is a problem with large argument values in the implementation of `skip` as of this writing (Java 1.0). The `long` passed as an argument is internally cast to an `int` because `skip` is implemented using the `read(byte[])` method. The problem with this is that arrays in Java are constrained to be no larger than an `int`. If skips larger than `int` are required, they must be implemented as multiple `int` skips.

The `skip` method returns a `long` that is used to indicate the number of bytes actually skipped. If the end of the input stream has already been reached when `skip` is called, a `-1` is returned. The following code fragment provides an example:

> `public long skipRecords (int num) {
> ` int recordSize = 512; //size of a record in bytes
> long rcode = 0;
> try {
> rcode = s.skip(num*recordSize); //skip num 512 byte records
> if (rcode > 0) {
> rcode /= recordSize; //compute records skipped
> }
> }
> catch (IOException e) { //handle IO exceptions
> System.out.println("Unknown IO error skipping " + num + " records");
> }
> return(rcode/recordSize);
> `}`

In this example, `skip` is used in a method that indexes into an input stream by number of fixed 512-byte records. A `try` statement is used to catch an exception during the `skip` process. The `catch` statement prints an error message if an `IOException` exception is generated. The method returns the number of records skipped, a `-1` if the skip was at end of input, or `0` if an exception occurred. (This example is based on `s` being a stream object that has already been opened as a variable global to this method.)

#### `close`

The `close` method is used to close an input stream that an application or applet no longer needs. Java closes input streams automatically when an application or applet exits, which is why a `close` statement has not been used in the preceding stream examples. However, it is good programming practice to close any resources an application no longer needs.

The `close` method throws the same `IOException` exception that `read` and `skip` do. This must be handled in an application's code, either by using a `try`/`catch`/`finally` structure or by adding `throw` statement to the class declaration.

> `public long closeStream () {
> ` try s.close(); //close input stream
> catch (IOException e) { //handle IO exceptions
> System.out.println("Unknown IO error closing input stream");
> }
> `}`

In this example, `close` is used in a method that encapsulates the `try` and `catch` functionality into a single location. A `try` statement is used to catch an exception during the `close` process. The `catch` statement prints an error message if an `IOException` exception is generated. (As in the `skip` example used previously, this example is based on `s` being a stream object that has already been opened as a variable global to this method.)

#### `available`

The `available` method is used to determine if some amount of data is ready to be read without blocking in the input stream and to test whether enough data is available for processing before some other method such as `read` is called. However, `available` does not return valid information for all input streams. Some input streams always return `0`, whereas others may return inconsistent numbers. This is due to the unknowns associated with the producer process and the implementation of the underlying Java code that handles the connection between the producer and consumer processes.

In other programming languages, the equivalent functionality of `available` is used to ensure that a required amount of data is available before issuing a `read` command. This is done because `read` often blocks until the read has completed. For applications that must continue doing other processing until all data needed is available, this is the only way to ensure that the application does not hang waiting for data.

In Java, threads can be used to handle this problem. By assigning a specific thread to do reading on an input stream, that thread can block, waiting for the required amount of input while other threads continue with needed processing. The easy availability of threads makes using `available` largely unnecessary. This is also why the incorrect or inconsistent results returned by `available` are not considered big problems. The syntax of `available` follows:

> `int available();`

The `available` method simply returns an `int` indicating the number of bytes in the input stream that can currently be read without blocking. The `available` method does not have any parameters. Note that the return value is an `int`. Streams can be of unlimited size, so even if more than an `int`'s worth of data is available, only an `int`'s worth is reported. The following code fragment provides an example:

> `public boolean isRecordReady () {
> ` int recordSize = 512; //size of a record in bytes
> boolean rcode = false;
> try {
> //test if at least 512 bytes are available
> if (s.available >= recordSize) {
> rcode = true;
> }
> }
> catch (IOException e) { //handle IO exceptions
> System.out.println("Unknown IO error checking for record availability");
> }
> return(rcode);
> `}`

In this example, `available` is used to determine if an entire fixed-length record of 512 bytes is available in the input stream. A `try` statement is used to catch an exception during the `available` test. The `catch` statement prints an error message if an `IOException` exception is generated. The method will return `true` if at least 512 bytes are ready or `false` if not. (As with `skip` and `close`, this example is based on `s` being a stream object that has already been opened as a variable global to this method.)

#### `mark`, `markSupported`, and `reset`

The `mark` method is used to mark a point in an input stream to which it may be necessary to return at a later time. This method is not available for all input stream types. A separate method called `markSupported` determines if a particular input stream supports this functionality. If `mark` is supported, you can use the `reset` method to return to the point indicated by `mark`.

The `mark`/`reset` methods have several limitations that make them useful only for specific applications. When `mark` is used, the program must specify a maximum amount of data that can go by before the `reset` method is called. If more than this amount of data goes by, `reset` will throw an exception. Also, there is no way to specify multiple `mark`s on an input stream. If `mark` is called again before a `reset` is done, the `mark` is simply moved to the new location with the new limit on how much can be read before a `reset` occurs. The syntax of `mark`, `markSupported`, and `reset` follows:

> `void mark(int readLimit);
> ` boolean markSupported();
> `void reset();`

The `mark` method accepts a single parameter of type `int` that indicates how much data in the input stream can go by before calling the `reset` method. The `markSupported` method has no arguments and simply returns a `boolean` value indicating whether the `mark` function is available for a given input stream. `reset` has no calling arguments and no return value. It simply resets the input stream to the point at which `mark` was called. The following code fragment provides an example:

> `public static boolean checkForPostScriptHeader (int size) {
> ` byte buffer[];
> String txt;
> buffer = new byte[size];
> if (s.markSupported() == false) {
> System.out.println("Input Stream does not support mark");
> System.exit(1);
> }
> try s.read(buffer);
> catch (IOException e) {
> System.out.println("Unknown IO error reading data stream");
> System.exit(2);
> }
> try s.reset();
> catch (IOException e) {
> System.out.println("Unknown IO error reseting data stream");
> System.exit(3);
> }
> txt = new String(buffer,size);
> if ((txt.indexOf("\n%!") != -1) || (txt.indexOf("%!") == 0))
> return(true);
> else
> return(false);
> `}`

This example is a method that checks a data input stream for a postscript header. If there is one, it will return `true`; otherwise it will return `false`. The `mark` and `reset` methods are used to return the data stream to its original location so that the calling routines can process the stream as needed.

The method starts by checking whether the `mark` method is available for this input stream using the `markSupported` method. If it is not, an application exit is forced. If `mark` is available, the input stream is marked with the passed-in size. This allows the calling application to specify how much data should be checked for a postscript header. After the input stream is marked, it is read into a buffer. If an `IOexception` occurs, a message is written to the screen and again the application exits. If the input stream is read successfully, it is then reset back to the location where the method was called. Again it tests for an `IOException` exception, and an error message and an exit occur if an exception is detected.

After the input stream is reset, the buffer is converted to a string value so that it can use the `indexOf` method to locate the postscript header. Finally, an `if` statement uses the `indexOf` method to locate the header. It is called twice: The first time it checks to see if any line begins with the necessary postscript header characters, and the second time it handles the special case at the beginning of the file where there is no newline character preceding the header. If a header is found, the method exits with a return value of `true`; otherwise, it exits with a return value of `false`.

### Output Streams

Output streams are the data streams generated by a producer process. As mentioned previously, stream classes and their associated methods are found in the `java.io` package. Every application or applet that uses streams must explicitly import this package at the beginning of the code with a standard `import` statement:

> `import java.io.*;`

As with input streams, there are many different classes of output streams. Each has its own purpose and can, of course, be extended or customized as needed by the programmer. Table 8.4 is a complete list of Java's output stream classes.

Table 8.4. Output stream classes.

`BufferedOutputStream` | Writes data to buffer to minimize the number of actual writes needed
`ByteArrayOutputStream` | Writes data to an array of bytes
`DataOutputStream` | Writes data objects to a stream rather than bytes like most other output streams
`FileOutputStream` | Writes data to a file
`FilterOutputStream` | Allows a stream to connect to subclasses of itself that can be used to filter the data
`OutputStream` | Abstracts the superclass to all output stream classes
`PipedOutputStream` | Writes data to a pipe connected to another process
`PrintStream` | Writes formatted data to the user's screen

Table 8.5 lists the three methods associated with output streams. Just like any other method in Java, these methods can be extended and customized as needed by the programmer.

Table 8.5. Output stream methods.

`write` | Writes data to an output stream
`flush` | Forces data to be written to pipe
`close` | Closes an output stream

#### `write`

The `write` method is the most basic of the output stream methods. This is the method an application uses to write data to a stream. As with the `read` method, there are several variations associated with it.

All `write` methods are based on a blocking write, meaning that when a `write` method is called, it will not return until all the data to be sent has been accepted or an exception occurs. When a call blocks, execution cannot continue until the call completes. This can cause problems if the programmer wants the application to continue if the `write` takes a significant amount of time. The solution, as with the input stream methods, is to use threads. If you put `write` into a separate thread, other executions can continue and the thread with `write` can take as long as it needs to complete the transaction.

All `write` methods also throw the `IOException` exception. This must be handled in an application's code, either by using a `try`/`catch`/`finally` structure or by adding `throws` to the class declaration. The syntax of `write` follows:

> `void write(int b);
> ` void write(byte[] buffer);
> `void write(byte[] buffer, int offset, int length)`

The variations on `write` almost exactly mirror those for `read`: The first simply writes a single byte to the output stream, and the second writes data to a buffer. The buffer is an array of bytes. The last version also writes a buffer, but will start at the indicated `offset` into the array and will only write `length` bytes. All cases of `write` have a return type of `void`. The only way to determine if an error occurred is to catch any exceptions that are thrown. Here is an example:

> `import java.io.*;
> ` public class MyMain {
> public static void main (String args[]) {
> FileOutputStream s; //declare s to a file output stream
> int n,ix; //declare for loop variables
> try { //use try to catch file open exceptions
> s = new FileOutputStream(args[0]); //open the output stream
> for (n=0; n < 20; n++) { //outer for loop
> for (ix=0x30; ix < 0x7b; ix++) { //inner for loop
> try { //use try to catch IO exceptions
> s.write(ix); //write character to output stream
> }
> catch (IOException e) { //handle IO exceptions
> System.out.println("Unknown IO error writing file " + args[0]);
> System.exit(2);
> }
> } &nb sp; //bottom of inner loop
> try {
> s.write('\n');
> } //write newline char to output stream
> catch (IOException e) { //handle IO exceptions
> System.out.println("Unknown IO error writing file " + args[0]);
> System.exit(3);
> }
> } &nb sp; //bottom of outer loop
> }
> catch (IOException e) { //handle file open exceptions
> System.out.println("Unknown IO error opening file " + args[0]);
> System.exit(1);
> }
> }
> `}`

In this example, `write` is used to write bytes to a file output stream. The filename itself is passed as the first argument on the command line. A stream object variable `s` is declared to be of type `FileOutputStream`. It is then initialized by opening the file output stream using the `new` operator. This results in either the creation of a new file using the filename specified on the command line or the rewriting of an existing file. This results in the file being opened, so a file `IOException` exception must be caught at this point if the file is not accessible. Next, two nested `while` loops are used to write a series of characters to the stream.

The inner loop writes all ASCII characters between `0` and `z`. The body of this loop starts out by calling the `write` method to write a single character to the output stream. `write` may return an `IOException` exception, so it is placed in a `try` statement. If `write` fails, a `catch` statement writes an error and the application aborts.

The outer loop simply causes the inner loop to be run 20 times. However, after every inner loop completes, the outer loop writes a `newline` character to the output stream. This makes the resulting output file more readable.

This example shows the basics for handling a simple output stream. It shows how to open an output stream, write data to it, and set up exception handling for both `open` and `write`.

#### `flush`

The `flush` method is used to force any data buffered for the output stream to be written to the output device. Some streams may be connected to slow or even hung consumer processes, in which cases `write` may block for an overly extended period of time, if not forever. In these situations, the `flush` method can be used to force Java to accept the data. Java may simply buffer the data itself, waiting for the consumer process to begin accepting data again or to die, thus closing the pipe. Remember that if a `write` is blocked, the only way for an application to force the `flush` to occur is to call `flush` using a different thread. This is another example of why putting a stream I/O call into its own thread is a good idea. The syntax of `flush` follows:

> `void flush();`

The `flush` method also throws the same `IOException` exception that `write` does. This must be handled in an application's code, either by using a `try`/`catch`/`finally` structure or by adding throws to the class declaration, as in the following example:

> `public void flushStream () {
> ` try {s.flush();} //close output stream
> catch (IOException e) { //handle IO exceptions
> System.out.println("Unknown IO error flushing output stream");
> }
> `}`

In this example, `flush` is used in a method that encapsulates the `try` and `catch` functionality into a single location. A `try` statement is used to catch any exceptions during the `close` process. The `catch` statement will print an error message if an `IOException` is generated. (This example is based on `s` being a stream object that has already been opened as a variable global to this method.)

#### `close`

The `close` method is virtually identical to the `close` used for input streams. It is used to close an output stream that an application or applet no longer needs. Java will automatically close output streams when an application or applet exits, which is why a `close` statement has not been used in the preceding stream examples. However, it is good programming practice to close any resources an application no longer needs. The syntax of `close` follows:

> `void close();`

The `close` method throws the same `IOException` exception that `write` and `flush` do. This must be handled in an application's code, either by using a `try`/`catch`/`finally` structure or by adding a `throw` statement to the class declaration. The following is an example:

> `public void closeStream () {
> ` try {s.close();} //close output stream
> catch (IOException e) { //handle IO exceptions
> System.out.println("Unknown IO error closing output stream");
> }
> `}`

In this example, `close` is used in a method that encapsulates the `try` and `catch` functionality into a single location. A `try` statement is used to catch an exception during the `close` process. The `catch` statement will print an error message if an `IOException` exception is generated. (This example is based on `s` being a stream object that has already been opened as a variable global to this method.)

### Summary of Streams

Streams are Java's way of reading and writing data to entities outside an application, such as files, networks, devices, or other processes. All streams in Java consist of a flow of 8-bit bytes. Some stream classes allow the writing of other object types, but internally they simply convert these objects to bytes. Streams can be broken into two main types: input streams and output streams.

Input streams accept data from an external source. Processes that accept input streams are known as consumers. You can use several methods with input streams: `read`, `skip`, `markSupported`, and `close` work with all input stream types; and `available`, `mark`, and `reset` only work with some input stream types. The `read` method is used to read data from an input stream. `skip` is used to skip over information in the input stream to get to data farther on. `close` simply closes an input stream. The `available` method can be used to determine if more data is available in an input stream, but the results returned by this method are not always accurate. The `markSupported` method is used to determine if a particular stream supports the `mark`/`reset` methods. These methods are used to mark a particular location in a stream and reset the stream back to that location.

Output streams produce data for an external destination. Processes that produce output streams are known as producers. You can use several methods with output streams: `write`, `flush`, and `close`. The `write` method is used to write data to an output stream. `flush` is used to force data to be written that may be buffered. `close` simply closes an output stream.

By using input and output streams, Java applications and applets can communicate with the rest of the world.

## Summary

This chapter examines the final pieces of the Java programming language: threads, exceptions, and streams.

The section on threads covers concurrent execution of multiple sections of code. The methods to create, initialize, start, stop, and destroy a thread are also discussed. Threads are a powerful part of the Java programming language, and a programmer who becomes versed in their use can write more powerful, robust, and user-friendly programs.

The section on exceptions covers Java's use of exceptions in place of the more normal return-type error code. Exceptions provide a more robust and extensible way to do error handling. The methods for catching and handling an exception are explained, as well as generation of new, customized exceptions. Because exceptions are simply another object in Java, all the benefits regarding code reuse and customization apply.

Finally, the section on streams covers Java's use of this construct to communicate with the outside world. Streams are a sequence of bytes. By using such a simple data format, Java applications do not have to have specific knowledge of where data is coming from or being written to. This in turn lends itself to simpler, more reusable code. The methods to open, read, write, and close a data stream are covered, in addition to more complex concepts such as rereading a part of a stream. Streams in Java provide a flexible-but above all, standardized-method for external communication.

This concludes the basics of Java programming. With the tool sets covered to this point, you are now ready to create Java applications that will serve your needs. Part IV, "The Java Application Programming Interface," covers the class libraries in Java.