简体   繁体   English

Java:为什么未关闭的 stream 不会抛出异常?

[英]Java: Why does an unclosed stream not throw an exception?

I wanted to write to a property file.我想写入一个属性文件。 But it silently never worked.但它默默地从来没有奏效。 Just from the code behavior I could not notice it.仅从代码行为中我无法注意到它。 I always had to open the properties file and look if the value changed.我总是不得不打开属性文件并查看值是否发生了变化。 But it never did.但它从来没有。 So actually I would expect to get an exception.所以实际上我希望得到一个例外。 The problem seemed to be that I did not close the InputStream before opening the OutputStream.问题似乎是我在打开 OutputStream 之前没有关闭 InputStream。 But I never got to know that.但我从来不知道这一点。 It cost me 3 days because I would expect either OutputStream or store function to give me some feedback.我花了 3 天时间,因为我希望 OutputStream 或 store function 能给我一些反馈。 Have a look at the code.看看代码。

File file = ResourceUtils.getFile("classpath:First.properties");
FileInputStream in = new FileInputStream(file);
Properties props = new Properties();
props.load(in);
System.out.println(props.getProperty("country"));
in.close();  // This I always forgot

FileOutputStream out = new FileOutputStream(file);
props.setProperty("country", "germany");
props.store(out, null);
System.out.println(props.getProperty("country"));
out.close();

A forgotten close() statement cannot cause an exception.忘记的close()语句不会导致异常。 From the perspective of your stream everything is okay.从您的 stream 的角度来看,一切都很好。 It just didn't wrote to its destination yet.它只是还没有写信给它的目的地。 Why should it?为什么要呢? Even when the whole program terminates there is no guaranty that the stream closes and writes its internal buffers out.[1]即使整个程序终止,也不能保证 stream 关闭并将其内部缓冲区写出。 [1]

You always have to call flush() or close() actively.您总是必须主动调用flush()close() The underlying implementation will then perform the actual write operation.然后底层实现将执行实际的写操作。

This mistake is so common that there is an extra Java-Feature to handle it.这个错误很常见,以至于有一个额外的 Java 功能来处理它。 It is called try-with-resources and prevents programmers from the evil consequences of missing close() statements.它被称为try-with-resources并防止程序员因缺少close()语句而产生不良后果。

Example:例子:

//use try-with-resources on out
private void saveProperties(Properties properties, String path) {
    try(PrintStream out = new PrintStream(new FileOutputStream(path))) {
        printProperties(properties,out);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
// you can pass System.out as well to print to console
private void printProperties(Properties properties, PrintStream out) {
    try {
        properties.store(out, null);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
//properties.load leaves the stream open, so you have to use try-with-resources
private Properties readProperties(String path) {
    try (FileInputStream in = new FileInputStream(path)) {
        Properties properties = new Properties();
        properties.load(in);
        return properties;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Related posts on Java Properties: Java 属性的相关帖子:

Related posts on Java Streams: Java Streams 上的相关帖子:

[1] See: Josh Bloch, Effective Java,(2nd ed.), Page 27. [1] 参见:Josh Bloch,有效 Java,(第 2 版),第 27 页。

Avoid finalizers.[...] It is entirely possible, even likely, that a program terminates without executing finalizers on some objects that are no longer reachable.避免使用终结器。[...] 完全有可能,甚至很可能,程序在没有对某些不再可访问的对象执行终结器的情况下终止。

As for the actual question "why does it not throw an exception", it's because there are cases you want the Stream to remain open.至于“为什么它不抛出异常”的实际问题,这是因为您希望 Stream 保持打开状态。

    class FileWriteSample implements Closeable {
        FileOutputStream writeTo;

        public FileWriteSample(String filename) throws IOException {
            writeTo = new FileOutputStream(filename);
            // should we expect an Exception here because we don't close the Stream?
            // we're planning to use it later on
        }
        public void write(String s) {
            // write to stream
        }
        public void close() throws IOException {
            writeTo.close();
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM