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教程。