简体   繁体   中英

Do closing InputStreamReader also close underlying InputStream?

JavaDoc for InputStreamReader doesn't say anything about closing underlying InputStream :

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

Description copied from class: Reader

Closes the stream and releases any system resources associated with it. Once the stream has been closed, further read(), ready(), mark(), reset(), or skip() invocations will throw an IOException. Closing a previously closed stream has no effect.

Do closing InputStreamReader also close underlying InputStream?

UPDATE In:

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

do I need to close conn.getInputStream() ?

InputStreamReader implementation direct close call to StreamDecoder which is native class. That's why I asked question (to you downvoter!).

As other answers and comments said, the answer is yes, it does close the InputStream. You can see for yourself with the following code:

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

Therefore, if you close the Reader, you don't need to also close the InputStream. However, I guess you are using try-with-resources everywhere (aren't you? ;) ) and the InputStream as well as the Reader will both be closed at the end of the try block. That doesn't matter, because an InputStream can be closed multiple times; it's a no-op if the stream is already closed.

If you want to avoid closing the InputStream, you can write a simple wrapper that does nothing when it is closed:

    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.

It depends on stream implementation. InputStream is just an "interface" in terms of close() . InputStreamReader will not close an interface. It will close the underlying data resource (like file descriptor) if it is. It will do nothing if close is override and empty in an implementation.

In OpenJdk StreamDecoder has a method

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

this.in is a InputStream from decoder constructor:

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

Here are examples of closing actions. ByteArrayInputStream :

Closing a ByteArrayInputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.

public void close() throws IOException {
}

FileInputStream differes:

Closes this file input stream and releases any system resources associated with the stream. If this stream has an associated channel then the channel is closed as well. After you closed the underlying instance it doesn't matter which interfaces were using it, it will be closed.

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();
       }
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM