Filter Streams (Auxiliary Streams)
Filter Streams do not have the independent capability to input or output data on their own. Instead, they wrap around another stream to add new functionalities (such as buffering data or transforming data types). This is an implementation of the Decorator Pattern.
1. Connecting Filter Streams
To use a filter stream, you must first create a Node Stream that directly transfers the data, and then pass this created node stream instance into the constructor of the filter stream to link them together.
// Create a Node Stream
FileInputStream fis = new FileInputStream("test.txt");
// Wrap the node stream with a Filter Stream (BufferedInputStream)
BufferedInputStream bis = new BufferedInputStream(fis);
// When reading data, utilize the methods of the Filter Stream!
bis.read();
2. Key Filter Streams
Various filter streams are provided depending on the purpose, such as improving performance or assisting in data conversion.
1) Buffered Filter Streams (Buffered)
Accessing the hard disk too frequently during I/O significantly degrades performance. This is the most vital filter stream that provides a memory buffer to collect data before sending or receiving it all at once. It is almost mandatory to use.
BufferedInputStream/BufferedOutputStreamBufferedReader/BufferedWriter(In particular,BufferedReader'sreadLine()is extremely useful because it reads text line-by-line.)
2) Converting Bytes to Characters (InputStreamReader, OutputStreamWriter)
When you receive data as bytes from external sources such as a network or user input, but it's actually textual data, this stream casts (converts) it into a Reader/Writer character processor. You can also specify the encoding type (e.g., UTF-8).
public class FilterStreamExample {
public static void main(String[] args) throws Exception {
// System.in is a byte-based (InputStream) node stream.
// We convert it to characters (InputStreamReader) and wrap it with buffering capabilities (BufferedReader).
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Please enter text: ");
String line = br.readLine(); // Effortlessly reading line-by-line
System.out.println("Input String: " + line);
br.close();
}
}
Beyond these, there are several other filter streams, such as DataInputStream capable of reading/writing primitive data types, and ObjectOutputStream which records entire object states into streams.