关闭InputStreamReader还关闭底层的InputStream吗?

时间:2017-06-21 10:20:52

标签: java

InputStreamReader的JavaDoc没有说明关闭基础InputStream

https://docs.oracle.com/javase/8/docs/api/java/io/InputStreamReader.html#close--

  

从类中复制的描述:Reader

     

关闭流并释放与其关联的所有系统资源。关闭流后,进一步的read(),ready(),mark(),reset()或skip()调用将抛出IOException。关闭之前关闭的流无效。

关闭InputStreamReader是否也会关闭底层的InputStream?

更新在:

InputStreamReader istream = new InputStreamReader(conn.getInputStream(), "UTF-8")
istream.close();

我是否需要关闭conn.getInputStream()

InputStreamReader实施直接close调用本地类的StreamDecoder。这就是为什么我问问题(给你下来的人!)。

2 个答案:

答案 0 :(得分:3)

正如其他答案和评论所说,答案是肯定的,它关闭了InputStream。您可以使用以下代码自己查看:

    InputStream is = new FileInputStream("D:\\a.txt");
    Reader r = new InputStreamReader(is);
    r.close();
    is.read();  // throws exception: stream is closed.

因此,如果您关闭Reader,则不需要也关闭InputStream。但是,我猜你到处都在使用try-with-resources(不是吗?;))并且在try块的末尾都会关闭InputStream和Reader。这并不重要,因为InputStream可以多次关闭;如果流已经关闭,那么它就是无操作。

如果你想避免关闭InputStream,你可以编写一个简单的包装器,它在关闭时什么都不做:

    class UncloseableInputStream extends FilterInputStream {
        public UncloseableInputStream(InputStream is) {
            super(is);
        }
        public void close() {
            // Do nothing.
        }
    }

    InputStream is = new FileInputStream("D:\\a.txt");
    Reader r = new InputStreamReader(new UncloseableInputStream(is));
    r.close();
    is.read();  // still works despite closing the reader.

答案 1 :(得分:0)

这取决于流实现。 InputStream只是一个"界面"就close()而言。 InputStreamReader不会关闭界面。如果是,它将关闭底层数据资源(如文件描述符)。如果close在实现中被覆盖并为空,则无效。

在OpenJdk StreamDecoder中有一个方法

void implClose() throws IOException {
    if(this.ch != null) {
        this.ch.close();
    } else {
        this.in.close();
    }
}

this.in是来自解码器构造函数的InputStream:

StreamDecoder(InputStream var1, Object var2, CharsetDecoder var3) {
    ...
    if(this.ch == null) {
        this.in = var1;
        ...
    }
    ...
}

以下是结束行动的示例。 ByteArrayInputStream

  

关闭ByteArrayInputStream无效。在关闭流之后可以调用此类中的方法,而不会生成IOException。

public void close() throws IOException {
}

FileInputStream个差异:

  

关闭此文件输入流并释放与该流关联的所有系统资源。如果此流具有关联的通道,则通道也将关闭。关闭基础实例后,哪些接口使用它并不重要,它将被关闭。

public void close() throws IOException {
    synchronized (closeLock) {
        if (closed) {
            return;
        }
        closed = true;
    }
    if (channel != null) {
       channel.close();
    }

    fd.closeAll(new Closeable() {
        public void close() throws IOException {
           close0();
       }
    });
}