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 in Example 6-6 has not one but two underlying streams. It does not modify the data that's written in any way; it merely writes that data on both of its underlying streams.
Example 6-6. The TeeOutputStream class
package com.elharo.io; import java.io.*; public class TeeOutputStream extends FilterOutputStream { private OutputStream out1; private OutputStream out2; public TeeOutputStream(OutputStream stream1, OutputStream stream2) { super(stream1); out1 = stream1; out2 = stream2; } public void write(int b) throws IOException { out1.write(b); out2.write(b); } public 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 { out1.flush( ); out2.flush( ); } public void close( ) throws IOException { out1.close( ); out2.close( ); } } |
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.
Example 6-7 demonstrates how one might use this class to write a TeeCopier program that copies a file into two separate, new files.
Example 6-7. The TeeCopier program
import java.io.*; import com.elharo.io.*; public class TeeCopier { public static void main(String[] args) throws IOException { if (args.length != 3) { System.out.println("Usage: java TeeCopier infile outfile1 outfile2"); return; } FileInputStream fin = new FileInputStream(args[0]); FileOutputStream fout1 = new FileOutputStream(args[1]); FileOutputStream fout2 = new FileOutputStream(args[2]); TeeOutputStream tout = new TeeOutputStream(fout1, fout2); BufferedStreamCopier.copy(fin, tout); fin.close( ); tout.close( ); } } |