关闭Java InputStreams

时间:2010-10-21 20:23:22

标签: java inputstream

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

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

使用上面的示例,无法显式调用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.
    }
}

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

8 个答案:

答案 0 :(得分:46)

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

答案 1 :(得分:28)

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

Properties props = new Properties();

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

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

答案 2 :(得分:25)

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

// create and load default properties
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("defaultProperties");
defaultProps.load(in);
in.close();

仅供参考,我检查了Apache Harmony Properties的{{3}}实现,并且在加载时关闭了流。

答案 3 :(得分:13)

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

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

答案 4 :(得分:12)

如果你正在使用Java 7+,你可以使用它:

try(InputStream is = new FileInputStream("message.properties")) {
    // ...
}

答案 5 :(得分:7)

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

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

在甲骨文网站上有一本名为Java Platform Performance的网站,其中讨论了附录中的终结者,它说:

  

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

答案 6 :(得分:2)

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

如果你可以导入Apache Commons IO,你可以使用非常方便的AutoCloseInputStream类:你包装你的InputStream然后你只需使用你的包装实例吧一旦达到输入结束或显式关闭流,就会自动关闭,以先到者为准。

答案 7 :(得分:0)

因为FileInputStream实现了finalize()并在`finalize中调用了close()

因此,如果使用频率不高,则无需关闭FileInputStream