在Java中处理流

在Java中处理流,java,stream,Java,Stream,在C#中,在处理流对象时,我几乎总是使用using模式。例如: using (Stream stream = new MemoryStream()) { // do stuff } 通过使用using块,我们确保在代码块执行之后立即在流上调用dispose 我知道Java没有使用关键字的等价物,但我的问题是,在Java中使用像FileOutputStream这样的对象时,我们是否需要进行任何整理以确保它得到处理?我正在看代码示例,我注意到它们没有做任何操作 我只是想知道Java在处理流

在C#中,在处理流对象时,我几乎总是使用
using
模式。例如:

using (Stream stream = new MemoryStream())
{
    // do stuff
}
通过使用
using
块,我们确保在代码块执行之后立即在流上调用dispose

我知道Java没有使用关键字的等价物,但我的问题是,在Java中使用像
FileOutputStream
这样的对象时,我们是否需要进行任何整理以确保它得到处理?我正在看代码示例,我注意到它们没有做任何操作


我只是想知道Java在处理流方面的最佳实践是什么,或者它是否足以让垃圾收集器处理它。

通常,您必须执行以下操作:

InputStream stream = null;
try {
   // IO stuff - create the stream and manipulate it
} catch (IOException ex){
  // handle exception
} finally {
  try {
     stream.close();
  } catch (IOException ex){}
}
但是apache提供了
IOUtils.closequity(流)
放在
finally
子句中,使其不那么难看。我认为在Java7中会有一些改进

更新:Jon Skeet做了一个非常有用的评论,异常的实际处理很少可能发生在类本身中(除非只是记录异常,但实际上并没有处理异常)。因此,您最好声明您的方法并抛出该异常,或者将其包装在自定义异常中(简单的原子操作除外)

在Java中使用语句(遗憾的是)并没有与之等价的
,尽管在Java7中也有类似的想法。(我想上次我看的时候,它们已经“过时了”,但我发现很难跟上Java7中功能的状态。)

Baicaly,您需要一个try/finally块:

InputStream stream = new FileInputStream(...);
try { 
    ...
} finally {
    stream.close();
}
然后是在close()失败的情况下如何处理
IOException
的问题,以及异常“覆盖”代码主体抛出的任何异常的问题——尽管后者在.NET中也是一个问题


通过使用静态的
close
closequity
方法,该类将处理
stream
为null的情况(如果在块之前声明变量,但在try块中赋值)。

如果有人好奇,Java 7中的新语法可能是:

do (BufferedInputStream bis = ...; BufferedOutputStream bos = ...) {
   ... // Perform action with bis and bos
}
(见附件)


这是一个堆栈溢出。

您想要的功能确实是在Java 7中引入的,名为“try with resources statement”(也称为自动资源管理(ARM))。代码如下:

try (InputStream in = new FileInputStream("foo.txt")) {
    ...
}  // This finally calls in.close()

创建流也会抛出
IOException
,因此它也应该在
try/catch/finally
中。但是使用上面的Bozho方法会导致原始异常被保留,对吧,因为他基本上是在吃可能抛出的IOException。另外,我认为您可能应该检查stream是否为null,否则NPE可能会导致,不是吗?@Bozho和dcp:通常,当我处理streams时,它位于一个声明抛出IOException的方法中,所以我很少在该级别捕获它。这就是你遇到问题的地方。这里给出的代码不需要检查空值,因为我正在调用构造函数:如果该方法返回时没有异常,
stream
肯定不会为空。您知道IOUtils.closequity(stream)是否处理空流,否则它可能抛出NPE并导致相同的问题(原始异常被吃掉)。是,
IOUtils
在关闭前检查null,因此没有npeac风险根据官方Java教程,您只在流不为null时关闭流。当然,您不能对
null
引用执行任何操作,除了对照它们进行检查,我发现在像这样的低级方法中,我实际上能够处理IOException是非常罕见的。它几乎总是涉及抛出某种异常。请注意,您还接受在关闭期间抛出的IOException;如果代码已经抛出了一个异常,那么这通常是正确的做法,否则可能会隐藏错误。例如,如果您向BufferedOutputStream写入多个项,但将其留给close()方法进行适当刷新,则吞咽异常会隐藏写入基本失败的事实。这是最好的语法,在出现错误的情况下,您可以保持从代码引发的异常和关闭异常