【问题标题】:How to check whether an OutputStream is closed如何检查 OutputStream 是否已关闭
【发布时间】:2012-01-29 03:58:23
【问题描述】:

是否有办法检查 OutputStream 是否已关闭而不尝试写入并捕获 IOException

例如,考虑以下人为的方法:

public boolean isStreamClosed(OutputStream out){
    if( /* stream isn't closed */){
        return true;
    }else{
        return false;
    }
}

你可以用什么替换/* stream isn't closed */

【问题讨论】:

  • 你需要解决的根本问题是什么?
  • 我怀疑 OP 希望避免处理异常。 ;)
  • 它来自于我防御性地思考我可能会收到什么样的错误输入,但这更像是一个假设性问题,加上“java检查输出流是否关闭”的顶级谷歌结果指向@ 987654321@ 似乎并没有真正回答这个问题

标签: java outputstream java-io


【解决方案1】:

在您尝试写入之前,底层流可能不知道它已关闭(例如,如果套接字的另一端关闭它)

最简单的方法是使用它并处理如果它关闭时会发生什么,而不是先对其进行测试。

无论你测试什么,你总是有机会得到一个 IOException,所以你不能避免异常处理代码。添加此测试可能会使代码复杂化。

【讨论】:

  • 这个答案与其他答案的区别在于没有像isClosed()这样的方法的理由,“在您尝试写入之前,底层流可能不知道它已关闭",因此接受,谢谢:)
  • isClosed() 在您最后调用 close() 后为真。这不是大多数人希望它做的事情。 ;)
【解决方案2】:

不幸的是,OutputStream API 没有像isClosed() 这样的方法。

所以,我只知道一种明确的方法:创建您的类StatusKnowingOutputStream,它包装任何其他输出流并实现其close() 方法,如下所示:

public void close() {
    out.close();
    closed = true;
}

现在添加方法isClosed()

public boolean isClosed() {
    return closed;
}

【讨论】:

  • 但是,在任何应用程序中都不应要求这样做。如果您自己的代码关闭了流 - 那么它也应该处理它的状态(关闭/打开)。但是,如果您从某个 3-rd 方库中获取流 - 它应该提供一些 boolean canIUseTheStream() 方法。
  • @bezmax,处理它的状态可能有点困难,假设您希望在您的业务方法中关闭它(您需要关闭它才能将其发送到其他地方)但您需要它也可以在finally 子句中处理,以便在发生异常时将其关闭。
  • 这是个好主意,但对于一般用途来说绝对不够。可能存在流从包装器外部关闭的情况,例如由操作系统或流提供者关闭。
【解决方案3】:

OutputStream 本身不支持这种方法。 Closable 接口的定义方式是,一旦您调用 close(),您将处理该 OutputStream。

也许您应该重新审视一下应用程序的设计,并检查您为什么不这样做,而您最终会得到一个关闭的 OutputStream 实例仍在您的应用程序中运行。

【讨论】:

    【解决方案4】:
    public boolean isStreamClosed(FileOutputStream out){
        try {
            FileChannel fc = out.getChannel();
            return fc.position() >= 0L; // This may throw a ClosedChannelException.
        } catch (java.nio.channels.ClosedChannelException cce) {
            return false;
        } catch (IOException e) {
        }
        return true;
    }
    

    这仅适用于 FileOutputStream!

    【讨论】:

      【解决方案5】:

      如果您在测试中这样做,请使用 mockito Spys,然后执行 verify

      我有效地进行了测试

      import static org.mockito.Mockito.spy;
      import static org.mockito.Mockito.times;
      import static org.mockito.Mockito.verify;
      
      import org.junit.Test;
      import java.io.InputStream;
      
      class MyTest {
          @Test
          public void testInputStreamCloseCalled() throws IOException {
              final InputStream spied = spy(...)
          
              // Do something that should call .close() on the spied InputStream
              spied.close()
      
              verify(spied, times(1)).close();
          }
      }
      

      ... 是您正在操作的输入流。

      也适用于 OutputStreams。

      【讨论】:

        【解决方案6】:

        没有。如果你自己实现,你可以写一个 isClosed 方法,但如果你不知道具体的类,那就不行。 OutputStream 只是一个抽象类。这是它的实现:

           /**
         * Closes this output stream and releases any system resources 
         * associated with this stream. The general contract of <code>close</code> 
         * is that it closes the output stream. A closed stream cannot perform 
         * output operations and cannot be reopened.
         * <p>
         * The <code>close</code> method of <code>OutputStream</code> does nothing.
         *
         * @exception  IOException  if an I/O error occurs.
         */
        public void close() throws IOException {
        }
        

        【讨论】:

        • OutputStream不是一个抽象类,因此它可以提供一些实现吗?
        • 是的,对不起,我的错。但事实并非如此。
        • 是的,很遗憾它没有像@AlexR 在他的回答中建议的那样 (stackoverflow.com/a/8655939/110255)
        【解决方案7】:

        通过使用 out.checkError()

        while(!System.out.checkError()) {
            System.out.println('hi');
        }
        

        在这里找到它:How do I get java to exit when piped to head

        【讨论】:

        • 这可能适用于 System.out PrintStream,实际上适用于任何 PrintStream,但一般不适用于 OutputStreams。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-23
        • 1970-01-01
        • 2011-03-22
        • 1970-01-01
        • 1970-01-01
        • 2010-12-22
        相关资源
        最近更新 更多