繁体   English   中英

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

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

我想写入一个属性文件。 但它默默地从来没有奏效。 仅从代码行为中我无法注意到它。 我总是不得不打开属性文件并查看值是否发生了变化。 但它从来没有。 所以实际上我希望得到一个例外。 问题似乎是我在打开 OutputStream 之前没有关闭 InputStream。 但我从来不知道这一点。 我花了 3 天时间,因为我希望 OutputStream 或 store function 能给我一些反馈。 看看代码。

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

忘记的close()语句不会导致异常。 从您的 stream 的角度来看,一切都很好。 它只是还没有写信给它的目的地。 为什么要呢? 即使整个程序终止,也不能保证 stream 关闭并将其内部缓冲区写出。 [1]

您总是必须主动调用flush()close() 然后底层实现将执行实际的写操作。

这个错误很常见,以至于有一个额外的 Java 功能来处理它。 它被称为try-with-resources并防止程序员因缺少close()语句而产生不良后果。

例子:

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

Java 属性的相关帖子:

Java Streams 上的相关帖子:

[1] 参见:Josh Bloch,有效 Java,(第 2 版),第 27 页。

避免使用终结器。[...] 完全有可能,甚至很可能,程序在没有对某些不再可访问的对象执行终结器的情况下终止。

至于“为什么它不抛出异常”的实际问题,这是因为您希望 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