关闭Java InputStreams

问题描述 投票:66回答:8

我对使用Java InputStreams时close()方法的使用有一些疑问。从大多数开发人员的经验来看,当不再需要InputStream时,应该始终在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.
    }
}

哪种方法更好和/或更有效?还是真的重要吗?

java inputstream
8个回答
26
投票

Properties Tutorial中的示例在加载后显式关闭FileInputStream,所以我认为可以肯定地认为load方法对此不负责。

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

仅供参考,我检查了Apache HarmonyProperties实现,它确实[[not关闭加载的流。


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


33
投票
我将使用try-with-resources(至少对于Java 7 +):

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

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

14
投票
如果您使用的是Java 7+,则可以使用此:

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


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

[函数关闭InputStream是不正常的。使用与非垃圾收集语言中的内存相同的约定:如果可能,打开流的人应该关闭流。否则,很容易让流保持打开状态(您以为函数会关闭它,但是它没有,或者什么...)


7
投票
看起来第一个代码示例最终依赖于FileInputStream中的finalize方法来实际关闭文件。我想说您的第二个示例更好,即使在两种情况下文件都没有关闭。

[在某些情况下,像Byte流这样,close什么都不做,可以省略,否则,我认为最好在finally块中明确关闭文件。如果打开它,则将其关闭。

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

几乎总是最好自己进行清理,而不要依赖终结器。使用终结器也可能会留下关键资源,这些资源在不确定的时间内无法恢复。如果您正在考虑使用终结器来确保及时释放重要资源,则可能需要重新考虑。

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

如果可以导入Apache Commons IO,则可以使用非常方便的AutoCloseInputStream s类:包装AutoCloseInputStream,然后只使用包装的实例,当实例已达到输入的末尾或显式关闭流时,以先到者为准。


0
投票
因为FileInputStream实现finalize()并在finalize中调用close()。因此,在不那么频繁使用时,不需要关闭FileInputStream
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.