What are filter input streams?
As you can see in the following hierarchies, there exist 4 subclasses for FilterInputStream and 3 subclasses for FilterOutputStream.
The hierarchy contains 12 input stream classes. All the classes can be divided into two categories – high-level streams and low-level streams. All the subclasses of FilterInputStream are known as high-level streams (there exists 4) and all the remaining are known as low-level streams (there are 8). Filter streams can be linked to another to have higher functionality, but subject to some rules.
Similar to input stream hierarchy, there exists output stream hierarchy also dealing with all output stream classes.
All the subclasses of FilterOutputStream are known as high-level streams (there exists 3) and all the remaining are known as low-level streams (there are 6). One filter stream can be linked to another to have higher functionality (output),
Java comes with low-level byte streams and high-level byte streams and similarly low-level and high-level character streams. Sub classes of FilterInputStream and FilterOutputStream are known as high-level streams. There are four high-level streams on input streams side – LineNumberInputStream, DataInputStream, BufferedInputStream and PushbackInputStream.
What is the job of Filter Streams Java?
The job of high-level streams is to add extra functionality to the existing streams. For example, LineNumberInputStream adds line numbers in the destination file that do not exist in the source file. DataInputStream increases performance with its readInt() and readLine() methods etc.
For higher functionality, one stream can be linked or chained to another, but obeying some simple rules. Chaining is very simple. The output of one stream becomes input to the other. Or to say, we pass an object of one stream as parameter to another stream constructor; this is how chaining is affected.
1. DataInputStream and DataOutputStream
DataInputStream and DataOutputStream are high-level as they are the subclasses of FilterInputStream and FilterOutputStream. These streams' extra functionality is that they can read or write integers, doubles and lines at a time, instead of byte by byte. This increases the performance to some extent; instead of reading and writing byte by byte with FileInputStream and FileOutputStream.
2. Giving Line Numbers - LineNumberInputStream
LineNumberInputStream is a subclass of FilterInputStream stream. We know each filter stream adds some extra functionality. The LineNumberInputStream does the extra work of adding line numbers that do not exist in the source.
3. Using Buffering to Enhance the Performance
Buffering of streams increases the performance to higher extents of few thousand times. For buffering, two streams exist in java.io package in byte streams category - BufferedInputStream and BufferedOutputStream. These high-level classes are subclasses of FilterInputStream and FilterOutputStream and their functionality is to increase the performance with buffer. These streams give an implicit system-defined buffer (generally, 2048 bytes) into which data is read and written. The buffer decreases the number of transfers between source file context area and destination file context area and thereby performance increases.
4. PushbackInputStream - Pushing unwanted extra character
Java permits to unread the unwanted bytes in a stream with the class PushbackInputStream. This is an unusual filter stream and it pushes back a character into the input stream. It is used to check a sequence of characters that meets with a condition or not. It can check the delimiter of a line like \r (carriage-return) or \n (life-feed) etc. If the sequence is broken out, it uses unread() method to push a byte back to the stream. Internally, the DataInputStream uses a PushbackInputStream to check for a line-feed (\n) sequence is crossed or not. For a program, you can go through PushbackReader.
In this category, two streams exist – FilterReader and FilterWriter. Filter streams are concrete classes that include some filtering capabilities as data is read or written by another stream. For example, a FilterReader object takes input from another Reader object and does processing for extra functionality and returns the processed data. A number of filter streams can be chained as one unit of a large filter which can ultimately turn out to a big processing.
It is an abstract class of character streams with filter capabilities on reading-side. Its equivalent in byte streams is FilterInputStream. It includes only one subclass, PushbackReader. Using PushbackReader is similar to PushbackInputStream. Following is the class signature
public class FilterReader extends Reader
FilterWriter is an abstract filter class for writing character data. Its equivalent on byte streams is FilterOutputStream. It does not have any subclasses.
Following is the class signature
public abstract class FilterWriter extends Writer
For a program on FileReader and FileWriter, refer Byte streams vs Character streams.