FilterReader和FilterWriter是Java IO中用于装饰字符流的抽象类,通过包装已有Reader/Writer并重写read/write方法实现自定义过滤逻辑,如去空格、大小写转换等,需注意异常传递、close行为及mark/reset支持。

FilterReader 和 FilterWriter 是 Java IO 中的装饰器抽象类,用于在字符流读写过程中添加自定义过滤逻辑。它们本身不直接处理底层数据,而是包装一个已有的 Reader 或 Writer,通过重写关键方法(如 read()、write())来拦截并修改字符流内容。
理解 FilterReader / FilterWriter 的作用机制
FilterReader 继承自 Reader,FilterWriter 继承自 Writer,二者都持有一个被包装的目标流(target reader/writer)。所有读写操作默认委托给目标流,但你可以在委托前后插入自己的逻辑——比如跳过空格、转大小写、替换敏感词、统计字符数等。
关键点:
- 必须调用
super.read()或super.write()才能真正读写底层流 - 重写
read(char[] cbuf, int off, int len)和write(char[] cbuf, int off, int len)更实用,因为单字符操作效率低 - 注意处理返回值:read 返回实际读取字符数(-1 表示 EOF),write 一般不返回值,但需确保写入完整
实现一个简单的“去空格” FilterReader
下面是一个跳过所有空白字符(包括空格、制表符、换行符)的自定义 FilterReader:
public class SkipWhitespaceReader extends FilterReader {
public SkipWhitespaceReader(Reader in) {
super(in);
}
<pre class="brush:php;toolbar:false;">@Override
public int read() throws IOException {
int ch;
do {
ch = super.read();
} while (ch != -1 && Character.isWhitespace((char) ch));
return ch;
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
if (len == 0) return 0;
char[] temp = new char[len];
int totalRead = 0;
while (totalRead <p>}</p>使用方式:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
Reader reader = new SkipWhitespaceReader(new StringReader("a b\t\nc"));
int ch;
while ((ch = reader.read()) != -1) {
System.out.print((char) ch); // 输出 "abc"
}实现一个“小写转大写”的 FilterWriter
这个 FilterWriter 在写入前将所有英文小写字母转为大写:
public class UppercaseWriter extends FilterWriter {
public UppercaseWriter(Writer out) {
super(out);
}
<pre class="brush:php;toolbar:false;">@Override
public void write(int c) throws IOException {
super.write(Character.toUpperCase((char) c));
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
char[] upper = new char[len];
for (int i = 0; i <p>}</p>使用方式:
Writer writer = new UppercaseWriter(new StringWriter());
writer.write("Hello World");
writer.close();
System.out.println(((StringWriter) writer).toString()); // 输出 "HELLO WORLD"
注意事项与最佳实践
写自定义 Filter 类时容易忽略的细节:
- 异常传递:务必把 IOException 向上抛出,不要吞掉;必要时可包装为 RuntimeException,但需明确语义
-
close() 行为:默认会调用被包装流的 close(),若需特殊清理(如刷新缓冲、释放资源),应重写 close() 并在末尾调用
super.close() -
mark/reset 支持:FilterReader 默认不支持 mark/reset,如需支持,要重写
markSupported()并同步委托 mark()/reset() 调用 - 线程安全:FilterReader/Writer 本身不保证线程安全,多线程访问同一实例时需外部同步
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










