Multitarget Output Streams

As a final example, I present two slightly unusual filter output streams that direct their data to multiple underlying streams. The TeeOutputStream class, given in Example 6.5, has not one but two underlying streams. The TeeOutputStream does not modify the data that’s written in any way; it merely writes it on both of its underlying streams.

Example 6-5. The TeeOutputStream Class



public class TeeOutputStream extends FilterOutputStream {

  OutputStream out1;
  OutputStream out2;

  public TeeOutputStream(OutputStream stream1, OutputStream stream2) {
    out1 = stream1;
    out2 = stream2;

  public synchronized void write(int b) throws IOException {

  public synchronized void write(byte[] data, int offset, int length) 
   throws IOException {
    out1.write(data, offset, length);
    out2.write(data, offset, length);

  public void flush() throws IOException {
  public void close() throws IOException {

It would be possible to store one of the output streams in FilterOutputStream’s protected out field and the other in a field in this class. However, it’s simpler and cleaner to maintain the parallelism between the two streams by storing them both in the TeeOutputStream class.

I’ve synchronized the write() methods to make sure that two different threads don’t try to write to the same TeeOutputStream at the same time. Depending on unpredictable ...

Get Java I/O now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.