Java Filter Streams

Unix popularized small programs that read from an input stream, processed it a bit, and wrote the result to an output stream. Usually done with pipes where A | B | C had B reading from the output of A and writing to the input of C, and had the obvious process overhead. Java provides something different, and perhaps less flexible, with filter stream classes.

  • public class FilterInputStream extends InputStream
  • public class FilterOutputStream extends OutputStream
  • public abstract class FilterReader extends Reader
  • public abstract class FilterWriter extends Writer

whose constructors are, respectively,

  • protected FilterInputStream(InputStream in)
  • protected FilterOutputStream(OutputStream out)
  • protected FilterReader(Reader in)
  • protected FilterWriter(Writer out)

Note that the constructor parameters to FilterInputStream, FilterOutputStream, FilterReader, and FilterWriter are the abstract classes. This is a bit of a pain; it forces you to use subclasses of these parameters in order to construct a subclass of FilterInputStream, FilterOutputStream, FilterReader or FilterWriter. We’ll see this in the next example set.

All the methods of these classes simply override the corresponding methods of the parent classes using in.read(), out.write(), etc. To use them, one subclasses one of them and once again overrides relevant classes. Other than providing sort of a template for such overrides, one could just as easily subclass InputStream, OutputStream, Reader, and Writer; however, using the filtered streams indicates intention and thus makes program code more understandable. If your intention is to filter, then it probably isn’t to change low level details of any read() or write() method.

Examples: filtering out successive blanks in a file stream

import java.io.*;
public class FilterMultipleBlanks extends FilterReader {
  public FilterMultipleBlanks(FilterReader in) {
    super(in);
    }; // end constructor
  char blank = ' ' ;
  boolean lastCharBlank = false;
  public int read() {
  int chr = super.read()
  if (lastCharBlank) {
    while ((char)chr == blank) chr = super.read();
      lastCharBlank = false;
      return chr;
    }; //end if lastCharBlank
    if ((char)chr == blank) lastCharBlank = true;
    return chr;
    }; // end read
  }; //end filter stream class

And next a test program for FilterMultipleBlanks:

import java.io.*;
public class FilterMultipleBlanksTest {
  public static void main (String[ ] args) throws IOException {
    FileReader in = new FileReader("test.txt");
    FilterMultipleBlanks fmb = new FilterMultipleBlanks(in);
    FileWriter out = new FileWriter("testresults.txt");
    int chr = fmb.read();
    while (chr != -1) {
      out.write(chr);
      chr = fmb.read();
      }; //end while
    fmb.close();
    out.close();
    }; //end main
  }; //end class

Note that FileReader in is passed to the constructor for FilterMultipleBlanks. Since FileReader is a subclass of Reader, this is ok.

The logic which skips over repeated blanks could be replaced by logic for logging, counting, or any other input filtering.

Advertisements

Tags: , , , , , , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: