在Java中打开流的正确方法是什么

jb.*_*jb. 4 java java-io

我将为物理专业的学生做一个关于Java的讲座,我想知道如何正确打开文件。

在我的许多专业应用程序中,我做了类似的事情:

  BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("file")));
  try{
    ....
  }finally {
     bufferedWriter.close();
  }
Run Code Online (Sandbox Code Playgroud)

恕我直言,没关系,即阅读器将始终关闭。

当我将其作为我的学生的示例时,我想知道如果构造函数InputStreamReader抛出异常会发生什么 --- FileInputStream 将打开,但它不会被我的代码关闭(因为这些对象是在 try-finally 之外创建的)堵塞。

那么这是正确的习语吗?如果是的话那为什么呢?如果打开流不是正确的习惯用法,请给我指出正确的习惯用法!

编辑:我正在寻找既正确又易于编写和理解的习语,物理学生是编程的初学者。

编辑:愚蠢的我,我复制了错误的示例 --- 如果我使用作家而不是读者,它会变得更加复杂。

Joh*_*erg 5

使用输入流读取

在 Java 7 之前,这就是你的做法

InputStream in = null;
try {
     in = new FileInputStream("simple.csv");
     BufferedReader buf = new BufferedReader(new InputStreamReader(in));
} finally {
  if (in != null) {
     try {
         in.close();
     } catch (IOException e) {}
  }
}
Run Code Online (Sandbox Code Playgroud)

对于Java 7你可以使用Closeable,类似

try (BufferedReader buf = new BufferedReader(...)) {}
Run Code Online (Sandbox Code Playgroud)

编辑:为什么我没有buf在上面关闭?看一下源代码BufferedReader.close()

public void close() throws IOException {
    synchronized (lock) {
        if (in == null)
            return;
        in.close();
        in = null;
        cb = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用输出流写入

编辑2:同样的原则也适用于作家。但是,如果您确实有兴趣在发生这种情况时刷新流IOException,那么您必须检查 和writerforstreamnull分别尝试关闭它们。不过,这给出了很多额外的代码。它可能看起来像这样:

BufferedWriter buf = null;
OutputStream out = null;
try {
    out = new FileOutputStream("file");
    buf = new BufferedWriter(new OutputStreamWriter(out));
} finally {
  if (buf != null) {
     try { buf.close(); } catch (IOException ex){}
  }
  if (out != null) {
     try { out.close(); } catch (IOException ex){}
  }
}
Run Code Online (Sandbox Code Playgroud)

这不是很漂亮。您可以引入一个辅助例程来关闭您的流或查看 Java 7 或Apache IOUtils