Java:返回BufferedInputStream后关闭

Java: Close after returning BufferedInputStream

我正在计划一个函数来创建和 returns 一个 InputStream,它又从另一个 InputStream 读取,因为 InputStream 的初始化并不简单,我想在多个地方使用它。考虑这个简单的例子:

private static InputStream openStream() throws IOException {
    Path path = Paths.get("/etc/passwd");
    InputStream inputStream = Files.newInputStream(path);
    return new BufferedInputStream(inputStream);
}

我将按如下方式使用此功能:

public static void main(String[] args) {
    try (InputStream stream = openStream()) {
        byte[] buffer = new byte[1024];
        int numBytes;
        while ((numBytes = stream.read(buffer, 0, buffer.length)) > 0) {
            System.out.printf("Just read %d bytes from stream!%n", numBytes);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

但是,我担心关闭此示例中的 BufferedInputStream 不会关闭其中的 InputStream。如果多次调用,这会导致孤立的文件句柄和内存泄漏吗?什么是更好的解决方案?

我能想到的一个简单的解决方案是定义一个可关闭的容器 class 并将两个输入流都放入其中 class。当调用 close() 时,此 class 将简单地关闭其所有打开的句柄。

class StreamContainer implements Closeable {

    private final InputStream[] inputStreams;

    public StreamContainer(InputStream... inputStreams) {
        this.inputStreams = inputStreams;
    }

    @Override
    public void close() throws IOException {
        for (InputStream inputStream : this.inputStreams) {
            inputStream.close();
        }
    }
}

但我想,可能会有更好的解决方案,内置机制或开发模式。或者也许应该避免这些结构?

在这种情况下你应该阅读BufferedInputStream的代码源,这是关闭定义

public void close() throws IOException {
    while(true) {
        byte[] buffer;
        if ((buffer = this.buf) != null) {
            if (!U.compareAndSetObject(this, BUF_OFFSET, buffer, (Object)null)) {
                continue;
            }

            InputStream input = this.in;
            this.in = null;
            if (input != null) {
                input.close();
            }

            return;
        }

        return;
    }
}

正如您在关闭 BufferedInputStream 时看到的那样,底层输入流也被关闭。

这是关闭的文档:

public void close() throws IOException Closes this input stream and releases any system resources associated with the stream. Once the stream has been closed, further read(), available(), reset(), or skip() invocations will throw an IOException. Closing a previously closed stream has no effect.