Java FilterWriter Class
Last modified: April 16, 2025
The java.io.FilterWriter
class is an abstract class for writing
filtered character streams. It serves as a base class for custom writer
implementations that transform or filter data before writing. The class itself
simply overrides all Writer methods with versions that pass requests to the
contained writer.
FilterWriter
extends Writer
and requires a
Writer
object to function. Subclasses should override some methods
to add filtering behavior. Unlike its input counterpart FilterReader, this class
is not commonly used directly in applications.
FilterWriter Class Overview
FilterWriter
provides a framework for filtering character output
streams. The class itself doesn't perform any filtering - subclasses must
implement the actual filtering logic. All methods delegate to the underlying
writer.
public abstract class FilterWriter extends Writer { protected Writer out; protected FilterWriter(Writer out); public void write(int c) throws IOException; public void write(char[] cbuf, int off, int len) throws IOException; public void write(String str, int off, int len) throws IOException; public void flush() throws IOException; public void close() throws IOException; }
The code above shows the structure of FilterWriter
. The protected
out
field holds the underlying writer. All write operations are
forwarded to this writer unless overridden by subclasses.
Creating a Custom FilterWriter
To create a useful FilterWriter, you must extend it and override methods to add filtering behavior. This example creates a simple uppercase converter that transforms all written characters to uppercase before passing them to the underlying writer.
import java.io.FilterWriter; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; class UppercaseFilterWriter extends FilterWriter { public UppercaseFilterWriter(Writer out) { super(out); } @Override public void write(int c) throws IOException { super.write(Character.toUpperCase(c)); } @Override public void write(char[] cbuf, int off, int len) throws IOException { char[] upperChars = new char[len]; for (int i = 0; i < len; i++) { upperChars[i] = Character.toUpperCase(cbuf[off + i]); } super.write(upperChars, 0, len); } @Override public void write(String str, int off, int len) throws IOException { write(str.toCharArray(), off, len); } } public class Main { public static void main(String[] args) throws IOException { StringWriter sw = new StringWriter(); UppercaseFilterWriter filter = new UppercaseFilterWriter(sw); filter.write("Hello, FilterWriter!"); filter.close(); System.out.println("Filtered output: " + sw.toString()); } }
This example demonstrates a custom FilterWriter
implementation. The
UppercaseFilterWriter
converts all characters to uppercase before
writing. The StringWriter
captures the output. All three write
methods are overridden to ensure consistent behavior.
FilterWriter with Character Replacement
This example creates a FilterWriter that replaces specific characters in the output stream. The replacement happens before writing to the underlying writer. This is useful for sanitizing output or implementing simple ciphers.
import java.io.FilterWriter; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; class ReplaceFilterWriter extends FilterWriter { private final char target; private final char replacement; public ReplaceFilterWriter(Writer out, char target, char replacement) { super(out); this.target = target; this.replacement = replacement; } @Override public void write(int c) throws IOException { super.write(c == target ? replacement : c); } @Override public void write(char[] cbuf, int off, int len) throws IOException { char[] filtered = new char[len]; for (int i = 0; i < len; i++) { filtered[i] = (cbuf[off + i] == target) ? replacement : cbuf[off + i]; } super.write(filtered, 0, len); } } public class Main { public static void main(String[] args) throws IOException { StringWriter sw = new StringWriter(); ReplaceFilterWriter filter = new ReplaceFilterWriter(sw, 'e', '3'); filter.write("Replace all 'e' characters with '3'"); filter.close(); System.out.println("Filtered output: " + sw.toString()); } }
The ReplaceFilterWriter
replaces all occurrences of a target
character with a replacement character. The constructor takes the target and
replacement characters. Both single-character and array write methods are
overridden to perform the replacement. The example replaces all 'e' characters
with '3'.
FilterWriter with HTML Escaping
This example implements a FilterWriter that escapes HTML special characters. This is useful when writing text that will be displayed in HTML to prevent XSS attacks or ensure proper rendering.
import java.io.FilterWriter; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; class HtmlEscapeFilterWriter extends FilterWriter { public HtmlEscapeFilterWriter(Writer out) { super(out); } @Override public void write(int c) throws IOException { switch (c) { case '&': super.write("&"); break; case '<': super.write("<"); break; case '>': super.write(">"); break; case '"': super.write("""); break; case '\'': super.write("'"); break; default: super.write(c); break; } } @Override public void write(char[] cbuf, int off, int len) throws IOException { for (int i = 0; i < len; i++) { write(cbuf[off + i]); } } @Override public void write(String str, int off, int len) throws IOException { write(str.toCharArray(), off, len); } } public class Main { public static void main(String[] args) throws IOException { StringWriter sw = new StringWriter(); HtmlEscapeFilterWriter filter = new HtmlEscapeFilterWriter(sw); filter.write(""); filter.close(); System.out.println("Escaped HTML: " + sw.toString()); } }
The HtmlEscapeFilterWriter
converts special HTML characters to
their entity equivalents. The single-character write method handles the
conversion, while the array and string methods delegate to it. This ensures all
output is properly escaped regardless of which write method is called.
Counting Characters with FilterWriter
This example creates a FilterWriter that counts the number of characters written. The count can be retrieved at any time, useful for logging or monitoring purposes.
import java.io.FilterWriter; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; class CountingFilterWriter extends FilterWriter { private int count = 0; public CountingFilterWriter(Writer out) { super(out); } public int getCount() { return count; } @Override public void write(int c) throws IOException { count++; super.write(c); } @Override public void write(char[] cbuf, int off, int len) throws IOException { count += len; super.write(cbuf, off, len); } @Override public void write(String str, int off, int len) throws IOException { count += len; super.write(str, off, len); } } public class Main { public static void main(String[] args) throws IOException { StringWriter sw = new StringWriter(); CountingFilterWriter filter = new CountingFilterWriter(sw); filter.write("Hello"); filter.write(", "); filter.write("world!".toCharArray()); filter.close(); System.out.println("Output: " + sw.toString()); System.out.println("Characters written: " + filter.getCount()); } }
The CountingFilterWriter
maintains a count of all characters written
through it. Each write method increments the counter appropriately. The count can
be retrieved using the getCount
method. This example writes three
segments and reports the total character count.
FilterWriter with Line Numbering
This example implements a FilterWriter that adds line numbers to the output. Each new line is prefixed with its line number, useful for creating numbered listings or logs.
import java.io.FilterWriter; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; class LineNumberingFilterWriter extends FilterWriter { private int lineNumber = 1; private boolean atStartOfLine = true; public LineNumberingFilterWriter(Writer out) { super(out); } @Override public void write(int c) throws IOException { if (atStartOfLine) { super.write(String.format("%3d: ", lineNumber++)); atStartOfLine = false; } super.write(c); if (c == '\n') { atStartOfLine = true; } } @Override public void write(char[] cbuf, int off, int len) throws IOException { for (int i = 0; i < len; i++) { write(cbuf[off + i]); } } @Override public void write(String str, int off, int len) throws IOException { write(str.toCharArray(), off, len); } } public class Main { public static void main(String[] args) throws IOException { StringWriter sw = new StringWriter(); LineNumberingFilterWriter filter = new LineNumberingFilterWriter(sw); filter.write("First line\nSecond line\nThird line"); filter.close(); System.out.println("Numbered output:\n" + sw.toString()); } }
The LineNumberingFilterWriter
adds line numbers to each new line.
It tracks when it's at the start of a line and inserts the line number prefix.
The line number increments after each newline character. All write methods
delegate to the single-character version to maintain consistent behavior.
FilterWriter with Indentation
This example creates a FilterWriter that maintains indentation levels. Each new line starts with a number of tabs corresponding to the current indentation level, useful for code generation or structured output.
import java.io.FilterWriter; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; class IndentingFilterWriter extends FilterWriter { private int indentLevel = 0; private boolean atStartOfLine = true; public IndentingFilterWriter(Writer out) { super(out); } public void increaseIndent() { indentLevel++; } public void decreaseIndent() { if (indentLevel > 0) { indentLevel--; } } @Override public void write(int c) throws IOException { if (atStartOfLine && c != '\n') { for (int i = 0; i < indentLevel; i++) { super.write('\t'); } atStartOfLine = false; } super.write(c); if (c == '\n') { atStartOfLine = true; } } @Override public void write(char[] cbuf, int off, int len) throws IOException { for (int i = 0; i < len; i++) { write(cbuf[off + i]); } } @Override public void write(String str, int off, int len) throws IOException { write(str.toCharArray(), off, len); } } public class Main { public static void main(String[] args) throws IOException { StringWriter sw = new StringWriter(); IndentingFilterWriter filter = new IndentingFilterWriter(sw); filter.write("First line\n"); filter.increaseIndent(); filter.write("Indented line\n"); filter.increaseIndent(); filter.write("More indented\n"); filter.decreaseIndent(); filter.write("Less indented\n"); filter.close(); System.out.println("Indented output:\n" + sw.toString()); } }
The IndentingFilterWriter
maintains indentation levels for new
lines. The increaseIndent
and decreaseIndent
methods
adjust the current level. Each new line starts with the appropriate number of
tabs. The writer tracks line starts to only insert indentation when needed.
Source
Java FilterWriter Class Documentation
In this article, we've covered the essential methods and features of the Java FilterWriter class. Understanding these concepts is crucial for creating custom output filters in Java applications.
Author
List all Java tutorials.