关闭Java InputStreams

Jas*_*ins 65 java inputstream

我对使用Java InputStreams时close()方法的用法有一些疑问.从我看到和从大多数开发人员那里读到的内容,你应该总是在不再需要的时候在InputStream上显式调用close().但是,今天我正在研究使用Java属性文件,我发现的每个例子都有这样的:

Properties props = new Properties();
try {
    props.load(new FileInputStream("message.properties"));
    //omitted.
} catch (Exception ex) {}
Run Code Online (Sandbox Code Playgroud)

使用上面的示例,无法显式调用close(),因为InputStream在使用后无法访问.我已经看到了许多类似的InputStreams用法,尽管它似乎与大多数人对明确关闭的说法相矛盾.我通读了Oracle的JavaDocs,并没有提到Properties.load()方法是否关闭了InputStream.我想知道这是否普遍可以接受,或者是否更喜欢做更像以下的事情:

Properties props = new Properties();
InputStream fis = new FileInputStream("message.properties");
try {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
} finally {
    try {
        fis.close();
    } catch (IOException ioex) {
        //omitted.
    }
}
Run Code Online (Sandbox Code Playgroud)

哪种方式更好和/或更有效?或者它真的重要吗?

Jon*_*Jon 48

Properties类将输入流包装在LineReader中以读取属性文件.由于您提供输入流,因此您有责任关闭它.

第二个例子是到目前为止处理流的更好方法,不要依赖别人为你关闭它.

你可以做的一个改进是使用IOUtils.closeQuietly()

关闭流,例如:

Properties props = new Properties();
InputStream fis = new FileInputStream("message.properties");
try {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
} finally {
    IOUtils.closeQuietly(fis);
}
Run Code Online (Sandbox Code Playgroud)

  • 不要在IOUtils 2.6上更换,不要使用,弃用和删除."请使用try-with-resources语句或手动处理抑制的异常." (4认同)

Dan*_*ina 33

我会尝试使用资源(至少对于Java 7+):

Properties props = new Properties();

try(InputStream fis = new FileInputStream("message.properties")) {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
}
Run Code Online (Sandbox Code Playgroud)

退出try块时,应自动调用close()调用.


Bil*_*ard 26

属性教程中的示例在FileInputStream加载后显式关闭,因此我认为可以安全地假设该load方法不对它负责,你是.

// create and load default properties
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("defaultProperties");
defaultProps.load(in);
in.close();
Run Code Online (Sandbox Code Playgroud)

仅供参考,我检查了Apache的和谐的执行性能,它并没有在负载关闭流.


小智 14

如果您使用的是Java 7+,则可以使用:

try(InputStream is = new FileInputStream("message.properties")) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)


Adr*_*ith 13

在文档中没有提到props.load将关闭输入流.您应该像您建议的那样在finally块中手动关闭输入流.

函数关闭是不正常的InputStream.同样的约定适用于非垃圾收集语言中的内存:如果可能,打开流的人应该关闭流.否则,很容易让一个流打开(你认为一个函数会关闭它,但它没有,或者什么......)


Nat*_*hes 7

看起来第一个代码示例最终依赖于FileInputStream中的finalize方法来实际关闭文件.我会说你的第二个例子更好,即使在这两种情况下文件都会关闭.

有些像Byte流这样的情况,close什么都不做,可以省略,否则我认为最好在finally块中显式关闭文件.如果你打开它,你关闭它.

Oracle网站上有一本名为Java Platform Performance的书,它在附录中讨论了终结器,它说:

你几乎总是更好地做自己的清理,而不是依靠终结器.使用终结器还可以留下在不确定的时间内无法恢复的关键资源.如果您正在考虑使用终结器来确保及时释放重要资源,您可能需要重新考虑.


Una*_*ivi 6

让我在其他人的答案中添加一些内容。

如果您可以导入Apache Commons IO,您可以使用非常方便的AutoCloseInputStreams 类:您包装您的InputStream实例,然后您只需使用您的包装实例,一旦到达输入末尾或当流被显式关闭,以先到者为准。