有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java资源:返回BufferedInputStream后关闭

我正在计划一个函数,该函数创建并返回一个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();
        }
    }
}

但我认为,可能有更好的解决方案,内置机制或开发模式。或者这些构造应该避免


共 (1) 个答案

  1. # 1 楼答案

    在这种情况下,您应该阅读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时所看到的,底层输入流也将关闭

    以下是close的文档:

    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.