关闭 Java InputStreams

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3991577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 08:03:10  来源:igfitidea点击:

Closing Java InputStreams

javainputstream

提问by Jason Watkins

I have some questions about the usage of the close() method when using Java InputStreams. From what I see and read from most developers, you should always explicitly call close() on an InputStream when it is no longer needed. But, today I was looking into using a Java properties file, and every example I have found has something like this:

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

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

With the above example, there is no way to explicitly call close() because the InputStream is unreachable after it is used. I have seen many similar uses of InputStreams even though it seems to contradict what most people say about explicitly closing. I read through Oracle's JavaDocs and it does not mention if the Properties.load() method closes the InputStream. I am wondering if this is generally acceptable or if it is preferred to do something more like the following:

在上面的例子中,没有办法显式调用 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.
    }
}

Which way is better and/or more efficient? Or does it really matter?

哪种方式更好和/或更有效?还是真的有关系?

采纳答案by Bill the Lizard

The examples in the Properties Tutorialclose the FileInputStreamexplicitly after loading, so I think it's safe to assume that the loadmethod isn't responsible for it, you are.

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

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

Just for reference, I checked the Apache Harmonyimplementation of Properties, and it does notclose the stream on load.

仅供参考,我检查了Apache的和谐的执行性能,它也不会在负载关闭流。

回答by Nathan Hughes

It looks like the first code sample ends up relying on the finalize method in FileInputStream to actually close the file. I would say your second example is better, even though in both cases the file does get closed.

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

There are cases like the Byte streams where close does nothing and can be omitted, otherwise I think it's better to explicitly close the file in a finally block. If you open it, you close it.

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

There is a book on Oracle's site called Java Platform Performancethat discusses finalizers in its appendix, it says:

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

You are almost always better off doing your own cleanup instead of relying on a finalizer. Using a finalizer can also leave behind critical resources that won't be recovered for an indeterminate amount of time. If you are considering using a finalizer to ensure that important resources are freed in a timely manner, you might want to reconsider.

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

回答by Adrian Smith

It doesn't mention in the documentation that props.loadwould close the input stream. You should close the input stream manually in a finally block like you suggest.

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

It isn't normal for a function to close an InputStream. The same convention applies as with memory in non-garbage-collected languages: If possible, the one who opens the stream should close the stream. Otherwise, it's very easy to leave a stream open (you think a function's going to close it, but it doesn't, or something...)

函数关闭InputStream. 相同的约定适用于非垃圾收集语言中的内存:如果可能,打开流的人应该关闭流。否则,很容易让流保持打开状态(您认为一个函数会关闭它,但它不会,或者其他什么......)

回答by Jon

The Properties class wraps the input stream in a LineReader to read the properties file. Since you provide the input stream, it's your responsibility to close it.

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

The second example is a better way to handle the stream by far, don't rely on somebody else to close it for you.

第二个示例是迄今为止处理流的更好方法,不要依赖其他人为您关闭它。

One improvement you could make is to use IOUtils.closeQuietly()

您可以进行的一项改进是使用IOUtils.closeQuietly()

to close the stream, e.g.:

关闭流,例如:

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

回答by Unai Vivi

Let me add a little something to other people's answers.

让我在其他人的答案中添加一些东西。

If you can import Apache Commons IO, you could make use of the ever-so-handy AutoCloseInputStreams classes: you wrap your InputStreamand then you just use your wrapped instance and it gets automatically closed as soon as the end of input has been reached or when the stream is explicitly closed, whichever comes first.

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

回答by Daniel Voina

I would go with a try-with-resources (at least for Java 7+):

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

Properties props = new Properties();

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

The close()call should be automatically called when the try block is exited.

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

回答by kwo2002

If you're using Java 7+ you can use this:

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

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

回答by lhl

Because FileInputStreamimplements finalize()and invoke close()in `finalize.

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

So when not so frequently used, there is no need to close FileInputStream

所以当不那么频繁使用时,没有必要关闭 FileInputStream