0

我正在计划一个函数,它创建并返回一个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它的内部。如果多次调用,这会导致孤立的文件句柄和内存泄漏吗?对此有什么更好的解决方案?

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

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

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

4

1 回答 1

2

在这种情况下,您应该阅读 的代码源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 关闭此输入流并释放与该流关联的所有系统资源。关闭流后,进一步的 read()、available()、reset() 或 skip() 调用将引发 IOException。关闭以前关闭的流没有效果。

于 2021-10-28T12:25:27.933 回答