The JavaTM Tutorial
Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Trail: Essential Java Classes
Lesson: I/O

How to Use Pipe Streams

Pipes are used to channel the output from one thread into the input of another. PipedReader (in the API reference documentation) and PipedWriter (in the API reference documentation) (and their input and output stream counterparts PipedInputStream (in the API reference documentation) and PipedOutputStream (in the API reference documentation)) implement the input and output components of a pipe. Why is this useful?

Consider a class that implements various string manipulation utilities, such as sorting and reversing text. It would be nice if the output of one of these methods could be used as the input for another so that you could string a series of method calls together to perform a higher-order function. For example, you could reverse each word in a list, sort the words, and then reverse each word again to create a list of rhyming words.

Without pipe streams, the program would have to store the results somewhere (such as in a file or in memory) between each step, as shown in the following figure.

Without a pipe, a program must store intermediate results.

Without a pipe, a program must store intermediate results.

With pipe streams, the output from one method could be piped into the next, as shown in this figure.

With a pipe, a program can pipe information directly from one thread to another.

With a pipe, a program can pipe information directly from one thread to another.

Let's look at a program, called RhymingWords (in a .java source file), that implements what's represented in the previous figure. This program uses PipedReader and PipedWriter to connect the input and output of its reverse and sort methods to create a list of rhyming words. Several classes make up this program.

First, let's look at the calling sequence of the reverse and sort methods from the main method:

FileReader words = new FileReader("words.txt");
Reader rhymingWords = reverse(sort(reverse(words)));
The innermost call to reverse takes a FileReader, which is opened on the file words.txt (in a .java source file) which contains a list of words. The return value of reverse is passed to sort, whose return value is then passed to another call to reverse.

Let's look at the reverse method; the sort method is similar and you will understand it once you understand reverse.

public static Reader reverse(Reader src) throws IOException {
    BufferedReader in = new BufferedReader(src);

    PipedWriter pipeOut = new PipedWriter();
    PipedReader pipeIn = new PipedReader(pipeOut);
    PrintWriter out = new PrintWriter(pipeOut);

    new ReverseThread(out, in).start();

    return pipeIn;
}
The statements in boldface create both ends of a pipe--a PipedWriter and a PipedReader-- and connect them by constructing the PipedReader "on" the PipedWriter. Whatever is written to the PipedWriter can be read from the PipedReader. The connection forms a pipe, as illustrated in the following figure.

Using PipedWriter and PipedReader to form a pipe.

Using PipedWriter and PipedReader to form a pipe.

The reverse method starts a ReverseThread (in a .java source file) that writes its output to the PipedWriter and then returns the PipedReader to the caller. The caller then arranges for a sorting thread to read from it. The sort method is exactly the same, except that it creates and starts a SortThread (in a .java source file).

Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.