Java:FilterInputStream相对于其他流有什么优势和用途?

24

我一直在阅读有关 InputStreamFileInputStreamByteArrayInputStream 的内容,它们的使用方式似乎很清晰(输出流也是如此)。

我对理解 FilterInputStream & FilterOutputStream 的用途感到困惑:

  • 与其他流类相比,使用它的优点是什么?
  • 何时应该使用它?
  • 请提供理论解释和一个基本示例。
3个回答

27

FilterInputStream装饰器模式的一个例子。

由于其构造函数是protected的,因此必须扩展此类。派生类将添加其他功能,但仍将公开InputStream的基本接口。

例如,BufferedInputStream 提供底层输入流的缓冲以加快读取数据的速度,而DigestInputStream在消耗数据时计算数据的加密哈希。

您可以使用此方法为依赖于InputStreamOutputStream API的现有代码添加功能。例如,假设您使用某个库将数据保存到OutputStream中。数据变得过大,因此您想要添加压缩功能。您可以修改应用程序,使其“装饰”当前创建的流与ZipOutputStream一起使用,而不是修改数据持久性库。该库将像使用缺少压缩的旧版本一样使用流。

3
好的,但是BufferedInputStream和DigestInputStream实际上会对底层流进行一些操作。FilterInputStream又是做什么的呢? - ed22
2
它并没有。基本上,它是一个邀请去扩展子类并重写读取和写入函数以添加任何你可能需要的新功能的机会。目前已经这样做的子类包括:BufferedInputStream、CheckedInputStream、CipherInputStream、DataInputStream、DeflaterInputStream、DigestInputStream、InflaterInputStream、LineNumberInputStream、ProgressMonitorInputStream和PushbackInputStream。 - Arlo Guthrie

4
您在想要装饰数据流时使用它们。
请记住,这些流类实例会包装另一个流实例(无论是否是这些实例的另一个子类),并添加一些功能,进行一些处理,使数据通过时做出一些更改。
例如,您可能希望从某个流中删除所有多余的空格。您可以创建自己的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格式之间转换行尾。
  • 添加延迟以模拟诸如调制解调器、串行端口或无线网络连接等缓慢的传输方式。

1
FilterInputStream并没有为实现过滤数据并正确支持markavailable等流提供任何帮助。你知道有哪个基类可以真正帮助实现输入流装饰器吗? - Aleksandr Dubinsky

2

FilterInputStreamFilterOutputStream旨在为希望实现自己的输入/输出流的开发人员提供便利。例如,BufferedInputStream等实现可能会在基本的InputStream API周围添加自己的装饰,同时委托给super类-在这种情况下是FilteredInputStream-他们不需要覆盖的方法。

既不建议直接使用FilterInputStream,也不建议直接使用FilterOutputStream


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接