我一直在阅读InputStream、FileInputStream、ByteArrayInputStream,以及它们的使用似乎很清楚(输出流也是如此)。
我正在努力理解FilterInputStream&FilterOutputStream:
- 与其他流类相比,使用它有什么优势
- 我应该什么时候使用它
- 请提供一个理论解释和一个基本的例子
FilterInputStream
是Decorator模式的一个示例。
这个类必须被扩展,因为它的构造函数是protected
。派生类将添加额外的功能,但仍然公开InputStream
的基本接口。
例如,BufferedInputStream
提供底层输入流的缓冲,以加快读取数据的速度,而DigestInputStream
在数据消耗时计算数据的加密哈希。
您可以使用它向依赖于InputStream
或OutputStream
API的现有代码添加功能。例如,假设您使用的某个库将数据保存到OutputStream
。数据增长过大,因此需要添加压缩。您可以修改应用程序,使其使用ZipOutputStream
"装饰"当前创建的流,而不是修改数据持久性库。库将使用流,就像它使用缺少压缩的旧版本一样。
当您想要装饰数据流时,可以使用它们。
请记住,这些流类实例将自己包裹在另一个流实例周围(无论是否是其中一个的另一个子类),并在数据通过时添加一些功能、添加一些处理、对数据进行一些更改。
例如,您可能希望从某个流中删除所有多个空格。您可以创建自己的FilterInputStream子类,并覆盖read()
方法。我不想麻烦所有的细节,但下面是子类中方法的一些java:
private boolean lastWasBlank = false;
public int read() {
int chr = super.read();
if (chr == ' ') {
if (lastWasBlank) {
return read();
} else {
lastWasBlank = true;
}
} else {
lastWasBlank = false;
}
return chr;
}
在现实生活中,您可能也会混淆其他两种read()
方法。
其他用途:
- 记录流经溪流的一切
- 复制"tee"实用程序,以便以两种方式处理正在读取的流
- 在Windows、Mac和Unix/Linux格式之间转换行尾
- 添加延迟以模拟慢速传输方法,如调制解调器、串行端口或无线网络连接
FilterInputStream和FilterOutputStream是为了简化希望实现自己的输入/输出流的开发人员的工作。像BufferedInputStream这样的实现可以在基本InputStream
API周围添加它们自己的装饰,同时在super
类上委派它们不需要覆盖的方法——在这种情况下是FilteredInputStream。
FilterInputStream
和FilterOutputStream
都不是为最终用户直接使用而设计的。