Manipulating data from a stream after it has been read, or before it is written, is often achieved by writing
Filter streams, rather than hardcoding the manipulation in a program. You'll learn about filters in Section
20.5.2 on page 516.
Exercise 20.1: Rewrite the TRanslateByte program as a method that translates the contents of an
InputStream onto an OutputStream, in which the mapping and the streams are parameters. For each
type of InputStream and OutputStream you read about in this chapter, write a new main method that
uses the translation method to operate on a stream of that type. If you have paired input and output streams,
you can cover both in one main method.
20.3. Character Streams
The abstract classes for reading and writing streams of characters are Reader and Writer. Each supports
methods similar to those of its byte stream counterpartInputStream and OutputStream, respectively.
For example, InputStream has a read method that returns a byte as the lowest 8 bits of an int, and
Reader has a read method that returns a char as the lowest 16 bits of an int. And where
OutputStream has methods that write byte arrays, Writer has methods that write char arrays. The
character streams were designed after the byte streams to provide full support for working with Unicode
characters, and in the process the contracts of the classes were improved to make them easier to work with.
The type tree for the character streams of java.io appears in Figure 20-2.
Figure 20-2. Type Tree for Character Streams in java.io
As with the byte streams, character streams should be explicitly closed to release resources associated with the
stream. Character stream synchronization policies are discussed in Section 20.5.1 on page 515.