FilterInputStream是Java IO中用于装饰底层输入流的抽象类,通过继承并重写read()等方法,在调用in.read()前后插入自定义逻辑(如跳过、计数、校验),其核心是委托+增强,且close()会自动关闭底层流。

FilterInputStream 是 Java IO 中用于装饰(decorate)底层输入流的抽象类,它本身不实现过滤逻辑,而是提供一个标准模板,让你通过继承它来插入自定义处理行为(如解密、校验、跳过字节、限流等)。使用它的核心思路是:**把原始 InputStream 传给父类构造器,然后重写 read() 等方法,在调用底层流之前或之后加入你的逻辑。**
继承 FilterInputStream 并重写关键 read 方法
必须至少重写一个 read() 方法(通常三个都要覆盖),否则默认行为会直接委托给底层流,起不到过滤作用。
-
read():读取单个字节,返回int(0–255)或-1(EOF) -
read(byte[] b):读入字节数组,返回实际读取长度 -
read(byte[] b, int off, int len):指定偏移和长度读取
所有重写方法中,应调用 super.read(...) 或直接操作 in 字段(FilterInputStream 的 protected 成员)获取原始数据,再按需处理。
示例:实现一个跳过前 N 个字节的 SkipInputStream
这个类在构造时指定要跳过的字节数,后续 read() 返回的是跳过之后的数据。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
public class SkipInputStream extends FilterInputStream {
private long skipLeft;
public SkipInputStream(InputStream in, long bytesToSkip) {
super(in);
this.skipLeft = bytesToSkip;
}
@Override
public int read() throws IOException {
while (skipLeft > 0) {
int b = in.read();
if (b == -1) return -1;
skipLeft--;
}
return in.read();
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
while (skipLeft > 0) {
long skipped = in.skip(skipLeft);
if (skipped == 0) {
int b1 = in.read();
if (b1 == -1) break;
skipLeft--;
} else {
skipLeft -= skipped;
}
}
return in.read(b, off, len);
}
}
使用方式:
InputStream raw = new FileInputStream("data.bin");
InputStream filtered = new SkipInputStream(raw, 4); // 跳过前 4 字节
int b = filtered.read(); // 读到第 5 字节
注意事项与常见陷阱
-
不要在构造器里做耗时或阻塞操作:FilterInputStream 构造器只负责保存
in,复杂初始化建议延迟到首次read() -
正确处理 EOF 和异常:每次调用底层
in.read()都可能返回-1或抛异常,需及时传递或转换 -
mark/reset 支持需手动维护:FilterInputStream 默认不支持标记重置;若需支持,应重写
mark()、reset()、markSupported(),并缓存跳过的/处理过的数据 -
避免重复关闭:FilterInputStream 的
close()会调用in.close(),子类不应额外关闭,也不应假设底层流未被关闭
替代方案:更现代的推荐方式
虽然 FilterInputStream 仍完全可用,但 Java 8+ 更推荐组合式设计:
- 用
InputStream+ lambda 或小工具方法封装逻辑(适合简单场景) - 使用
java.util.stream.Stream处理已加载的数据(非实时流式) - NIO.2 中用
Files.newInputStream()配合自定义ByteBuffer处理器(更底层、更灵活) - 第三方库如 Apache Commons IO 提供了
CountingInputStream、ProxyInputStream等开箱即用的装饰器
不过,理解 FilterInputStream 的原理,对掌握装饰器模式和 Java IO 底层机制仍有不可替代的价值。

















