The JavaTM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: Essential Java Classes
Lesson: Reading and Writing (but no 'rithmetic)

## How to Use Pipe Streams

> `PipedReader` and `PipedWriter` (and their input and output stream counterparts `PipedInputStream` and `PipedOutputStream`) implement the input and output components of a pipe. Pipes are used to channel the output from one program (or thread) into the input of another. 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 some 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 here:

> This figure has been reduced to fit on the page.
> Click the image to view it at its natural size.
> With pipe streams, the output from one method could be piped into the next, as shown in this figure:

> Next, we investigate a program that implements what's represented by the diagram in the previous figure. This program uses `PipedReader` and `PipedWriter` to connect the input and output of its `reverse` and `sort` methods in order to create a list of rhyming words. Several classes make up this program. This section shows and discusses only the elements of the program that read from and write to the pipes. Follow the code links presented here to see the whole program.

> First, let's look at the calling sequence of the `reverse` and `sort` methods from the `main` method in the `RhymingWords` class:

> >     FileReader words = new FileReader("words.txt");
> >     Reader rhymingWords = reverse(sort(reverse(words)));

> The innermost call to `reverse` takes a `FileReader` opened on the file `words.txt` that 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 source) {
> >         BufferedReader in = new BufferedReader(source);

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

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

> >         return pipeIn;
> >     }

> The bold statements in `reverse` create both ends of a pipe--a `PipedWriter` and a `PipedReader`-- and connects them by constructing the `PipedReader` "on" the `PipedWriter`. Whatever's written to the `PipedWriter` can be read from the `PipedReader`. The connection forms a pipe, as illustrated here:

> `reverse` starts a `ReverseThread` 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`.

### Using Streams to Wrap Other Streams

> The `reverse` method contains some other interesting code; in particular, these two statements:

> >     BufferedReader in = new BufferedReader(source);
> >     ...
> >     PrintWriter out = new PrintWriter(pipeOut);

> The first line opens a `BufferedReader` on `source`, the argument to reverse (a `Reader`). This essentially "wraps" `source` in a `BufferedReader`. The program reads from the `BufferedReader`, which in turn reads from `source`. The program does this so that it can use `BufferedReader`'s convenient `readLine` method. Similarly, the `PipedWriter` is wrapped in a `PrintWriter` so that the program can use `PrintWriter`'s convenient `println` method. You will often see streams wrapped in this way so as to combine the various features of the many streams.

> Try this: Write another version of this program that uses input streams and output streams in place of readers and writers. See
> - `RhymingWords`
> - `ReverseThread`
> - `SortThread`
> for the solution.

| Start of Tutorial > Start of Trail > Start of Lesson | Search