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

时间:2012-03-31 20:19:23

标签: java java-io

我将为物理学学生开设Java讲座,我想知道如何正确打开文件。

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

  BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("file")));
  try{
    ....
  }finally {
     bufferedWriter.close();
  }

这是恕我直言,即读者将始终关闭。

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

这是正确的成语,如果是这样,为什么呢?如果打开流不正确,请指出正确的一个!

编辑:我正在寻找既正确且非常容易编写和理解的习语,物理系学生也是编程的初学者。

编辑:愚蠢的我,我复制错误的例子---如果不是读者,我使用Writers它会变得更复杂。

2 个答案:

答案 0 :(得分:4)

使用输入流读取

在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) {}
  }
}

对于Java 7,您可以使用Closeable,例如

try (BufferedReader buf = new BufferedReader(...)) {}

编辑:为什么我不关闭buf以上?查看BufferedReader.close()

的源代码
public void close() throws IOException {
    synchronized (lock) {
        if (in == null)
            return;
        in.close();
        in = null;
        cb = null;
    }
}

使用输出流

进行写入

编辑2:同样的原则适用于作家。但是,如果您真的有兴趣在IOException发生时刷新流,那么您必须同时检查writerstream null并尝试分别关闭它们。但是,这提供了许多额外的代码。它可能看起来像这样:

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){}
  }
}

它不是很漂亮。您可以引入帮助程序来关闭流或查看Java 7或Apache IOUtils

答案 1 :(得分:0)

在这种特殊情况下(嵌套构造函数),FileInputStream将保持打开状态。你必须这样做(如果你真的需要确保流关闭):

final FileInputStream fis = new FileInputStream("");
try
{
    final BufferedReader br = new BufferedReader(new InputStreamReader(fis));
    // ...
}
finally
{
    fis.close();
}

关闭FileInputStream就足够了。

编辑:可以将相同的逻辑应用于编写者。如果打开FileOutputStream失败,它会抛出一个异常,阻止执行try / finally块。如果任何其他编写器构造函数失败,输出流仍然会通过final子句关闭。

相关问题