Java基础教程(九十六)IO之Filter模式:深度解析 Java IO 的 Filter 模式,打造流式操作的超级过滤器
Java IO 中的 Filter 模式(装饰器模式)通过层层包裹基础流(如 FileInputStream),为 I/O 操作提供灵活的功能扩展。核心类 FilterInputStream/FilterOutputStream 作为抽象装饰器,其子类(如 BufferedInputStream, DataInputStream)在不改变原始流结构的前提下,动态添加缓冲、数据类型处理、行读取等增强
Java IO 中的 Filter 模式(装饰器模式)通过层层包裹基础流(如 FileInputStream),为 I/O 操作提供灵活的功能扩展。核心类 FilterInputStream/FilterOutputStream 作为抽象装饰器,其子类(如 BufferedInputStream, DataInputStream)在不改变原始流结构的前提下,动态添加缓冲、数据类型处理、行读取等增强功能。该模式解耦了基础 I/O 与扩展功能,支持功能组合(如先缓冲再转换),显著提升代码复用性与可维护性。本文剖析其运作机制,并演示如何自定义 FilterOutputStream 实现字母转大写,揭示其作为 Java I/O 灵活扩展基石的核心价值。
一、为何需要 Filter 模式?
基础流(如 FileInputStream, FileOutputStream)仅提供字节读写能力。现实需求往往更复杂:
- 缓冲加速(
BufferedInputStream) - 读写基本数据类型(
DataInputStream) - 按行处理文本(
BufferedReader)
直接修改基础流类会破坏开闭原则。Filter 模式应运而生 —— 装饰器模式(Decorator Pattern) 的经典应用。
二、Filter 模式核心机制
- 抽象装饰器:
FilterInputStream和FilterOutputStream。
-
- 内部持有一个被装饰的底层流对象 (
protected InputStream in;/protected OutputStream out;)。 - 继承自
InputStream/OutputStream,重写关键方法(如read(),write()),默认将调用委托给持有的底层流。
- 内部持有一个被装饰的底层流对象 (
- 具体装饰器: 继承自
FilterXXXStream。
-
- 在委托调用前后或过程中加入增强逻辑。
- 例如
BufferedInputStream.read()先检查内部缓冲区,为空时从底层流读取一大块数据填充缓冲区。
// FilterInputStream 关键源码示意
public class FilterInputStream extends InputStream {
protected volatile InputStream in; // 核心:持有被装饰的流
protected FilterInputStream(InputStream in) { this.in = in; }
public int read() throws IOException { return in.read(); } // 默认委托
// ... 其他方法类似委托
}
- 灵活组合: 可多层嵌套装饰器。
// 组合:文件流 -> 缓冲流 -> 数据流 (读int/double等)
DataInputStream dis = new DataInputStream(
new BufferedInputStream(
new FileInputStream("data.bin")));
int num = dis.readInt(); // 高效读取int
三、实战:自定义大写转换过滤器
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* 自定义 FilterOutputStream:将写入的英文字母转换为大写
*/
public class UpperCaseFilterOutputStream extends FilterOutputStream {
public UpperCaseFilterOutputStream(OutputStream out) {
super(out); // 调用父类构造,传入被装饰的底层流
}
// 核心增强:重写write(int),在写入前转换字符
@Override
public void write(int b) throws IOException {
// 只转换小写字母 (a-z), 其他字符原样写入
if (b >= 'a' && b <= 'z') {
b = b - ('a' - 'A'); // 转换为大写 ASCII 码
}
super.write(b); // 委托给持有的底层流执行实际写入
}
// 重写write(byte[], int, int) 提升批量写入效率
@Override
public void write(byte[] b, int off, int len) throws IOException {
for (int i = off; i < off + len; i++) {
write(b[i]); // 复用我们增强的write(int)方法
}
}
}
使用示例:
import java.io.FileOutputStream;
import java.io.IOException;
public class FilterDemo {
public static void main(String[] args) {
// 组合:文件流 -> 自定义大写过滤器
try (OutputStream fos = new FileOutputStream("output.txt");
UpperCaseFilterOutputStream ucos = new UpperCaseFilterOutputStream(fos)) {
String text = "Hello, Filter World! 123\n";
byte[] bytes = text.getBytes();
ucos.write(bytes); // 写入时自动转大写
System.out.println("数据已写入并转换!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果 (output.txt 内容):
HELLO, FILTER WORLD! 123
四、关键优势与注意事项
- 优势:
-
- 开闭原则: 不修改基础流即可扩展功能。
- 灵活组合: 按需叠加功能(缓冲+加解密+压缩)。
- 职责清晰: 每个装饰器只负责单一增强。
- 透明性: 使用方式与基础流一致 (
read/write)。
- 注意:
-
- 装饰顺序: 顺序可能影响结果和性能(如缓冲应靠近底层流)。
- 资源关闭: 关闭最外层流会自动关闭所有内嵌流(通常无需手动关闭内部流)。
- NIO.2 补充: Java NIO 的 Channel 和 Buffer 提供了更高性能的替代方案,但装饰器模式在传统 IO 和流式 API 中仍广泛应用。
结语: Filter 模式是 Java I/O 灵活性的核心支柱。理解其装饰器本质(FilterXXXStream + 委托 + 功能增强)和组合威力,是掌握高效、可扩展流处理的关键。自定义过滤器(如本文的 UpperCaseFilterOutputStream)将基础 I/O 变成了可插拔的功能管道 —— 你的代码,就是最好的插件。
更多推荐

所有评论(0)