As mentioned earlier, streams provide communication of data at the byte level, and are used for either reading or writing. Streams for reading inherit from a common superclass, the java.io.InputStream class, shown in Figure 4-3. Likewise, streams used for writing data inherit from the superclass java.io. OutputStream, shown in Figure 4-4. These are abstract classes; they cannot be instantiated. Instead, an appropriate subclass for the task at hand is created. Several streams inherit directly from either InputStream or OutputStream, but most inherit from a filter stream.