在使用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.
}
}
哪种方式更好和/或更有效?或者它真的重要吗?
答案 0 :(得分:46)
Properties类将输入流包装在LineReader中以读取属性文件。由于您提供输入流,因此您有责任将其关闭。
第二个例子是到目前为止处理流的更好方法,不要依赖别人为你关闭它。
进行一项改进关闭流,例如:
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