1

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

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

2 回答 2

1

至于“为什么它不抛出异常”的实际问题,这是因为在某些情况下您希望 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();
        }
    }
于 2020-05-14T07:53:51.863 回答
1

被遗忘的close()语句不会导致异常。从您的流的角度来看,一切都很好。它只是还没有写信给它的目的地。为什么要呢?即使整个程序终止,也不能保证流关闭并将其内部缓冲区写出。 [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 流的相关文章:

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

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

于 2020-05-13T08:53:58.963 回答