在Java中处理流
在C#中,在处理流对象时,我几乎总是使用在Java中处理流,java,stream,Java,Stream,在C#中,在处理流对象时,我几乎总是使用using模式。例如: using (Stream stream = new MemoryStream()) { // do stuff } 通过使用using块,我们确保在代码块执行之后立即在流上调用dispose 我知道Java没有使用关键字的等价物,但我的问题是,在Java中使用像FileOutputStream这样的对象时,我们是否需要进行任何整理以确保它得到处理?我正在看代码示例,我注意到它们没有做任何操作 我只是想知道Java在处理流
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()方法进行适当刷新,则吞咽异常会隐藏写入基本失败的事实。这是最好的语法,在出现错误的情况下,您可以保持从代码引发的异常和关闭异常