Java FilterWriter 类
最后修改时间:2025 年 4 月 16 日
java.io.FilterWriter
类是一个用于写入过滤字符流的抽象类。它充当自定义写入器实现的基类,这些实现会在写入前转换或过滤数据。该类本身只是用将请求传递给包含的写入器的版本覆盖所有 Writer 方法。
FilterWriter
扩展了 Writer
并需要一个 Writer
对象才能运行。子类应该重写某些方法以添加过滤行为。与它的输入对应物 FilterReader 不同,这个类通常不直接在应用程序中使用。
FilterWriter 类概述
FilterWriter
为过滤字符输出流提供了一个框架。该类本身不执行任何过滤 - 子类必须实现实际的过滤逻辑。所有方法都委托给底层写入器。
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; }
上面的代码显示了 FilterWriter
的结构。受保护的 out
字段保存着底层的写入器。除非被子类覆盖,否则所有写入操作都将转发给此写入器。
创建自定义 FilterWriter
要创建一个有用的 FilterWriter,您必须扩展它并覆盖方法以添加过滤行为。此示例创建了一个简单的转换为大写的转换器,它在将所有写入的字符传递到底层写入器之前将其转换为大写。
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()); } }
此示例演示了一个自定义 FilterWriter
实现。UppercaseFilterWriter
在写入前将所有字符转换为大写。StringWriter
捕获输出。所有三个写入方法都被重写以确保行为一致。
带有字符替换的 FilterWriter
此示例创建一个 FilterWriter,用于替换输出流中的特定字符。替换发生在写入到底层写入器之前。这对于清理输出或实现简单的密码非常有用。
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()); } }
ReplaceFilterWriter
将所有目标字符的出现替换为替换字符。构造函数接受目标字符和替换字符。单字符和数组写入方法都被重写以执行替换。此示例将所有 'e' 字符替换为 '3'。
带有 HTML 转义的 FilterWriter
此示例实现了一个 FilterWriter,用于转义 HTML 特殊字符。这在编写将显示在 HTML 中的文本时非常有用,以防止 XSS 攻击或确保正确的渲染。
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()); } }
HtmlEscapeFilterWriter
将特殊 HTML 字符转换为其实体等价物。单字符写入方法处理转换,而数组和字符串方法将其委托给它。这确保所有输出都得到正确转义,无论调用哪个写入方法。
使用 FilterWriter 计数字符
此示例创建一个 FilterWriter,用于计算写入的字符数。该计数可以随时检索,对于日志记录或监视目的很有用。
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()); } }
CountingFilterWriter
维护通过它写入的所有字符的计数。每个写入方法都会相应地增加计数器。可以使用 getCount
方法检索计数。此示例写入三个段并报告总字符数。
带有行号的 FilterWriter
此示例实现了一个 FilterWriter,它将行号添加到输出中。每行新行都以其行号为前缀,这对于创建编号列表或日志很有用。
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()); } }
LineNumberingFilterWriter
将行号添加到每一行新行。它跟踪它何时位于一行的开头,并插入行号前缀。行号在每个换行符后递增。所有写入方法都委托给单字符版本以保持一致的行为。
带有缩进的 FilterWriter
此示例创建了一个 FilterWriter,用于维护缩进级别。每一行新行都以对应于当前缩进级别的多个制表符开头,这对于代码生成或结构化输出很有用。
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()); } }
IndentingFilterWriter
维护新行的缩进级别。increaseIndent
和 decreaseIndent
方法调整当前级别。每一行新行都以适当数量的制表符开头。写入器跟踪行开头,以便仅在需要时插入缩进。
来源
在本文中,我们介绍了 Java FilterWriter 类的基本方法和特性。理解这些概念对于在 Java 应用程序中创建自定义输出过滤器至关重要。
作者
列出所有Java教程。