InputStream和OutputStream应该如何关闭?

9

我正在使用以下代码关闭与服务器连接的输入流和输出流:

try {
        if (mInputStream != null) {
            mInputStream.close();
            mInputStream = null;
        }

        if (mOutputStream != null) {
            mOutputStream.close();
            mOutputStream = null;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

然而,这些流并没有关闭,它们仍然存在。如果我再次连接,就会有两个不同的InputStream。在catch部分没有捕获到任何异常。

我做错了什么?


4
不管是否抛出异常,你都应该将关闭语句放在finally块中,以确保流始终能够正确关闭。这样做不会改变原意,同时让内容更加通俗易懂。 - McStretch
“streams is still alive” 是什么意思? - Peter Knego
调用 close 方法后,流仍然从服务器接收数据。当我关闭应用程序时,连接才会关闭。^^;;; - mooongcle
1
@moongcle:你的流并不是“仍在从服务器接收数据”。流不会与服务器通信,套接字才会与服务器通信。 - CommonsWare
1个回答

19

编辑:添加了Java 8的try-with-resources示例,因为该语言自首次发布以来已经发展。

如果您正在使用Java 7(或更低版本),则您发布的代码存在两个问题:

  1. .close()调用应该在finally块中处理。这样它们将始终关闭,即使它掉入了某处的catch块中。
  2. 您需要在每个.close()调用中单独使用try/catch块,否则您可能会留下其中一个未关闭。如果尝试关闭输入流失败,则会跳过关闭输出流的尝试。

您需要像这样做:

    InputStream mInputStream = null;
    OutputStream mOutputStream = null;
    try {
        mInputStream = new FileInputStream("\\Path\\MyFileName1.txt");
        mOutputStream = new FileOutputStream("\\Path\\MyFileName2.txt");
        //... do stuff to your streams
    }
    catch(FileNotFoundException fnex) {
        //Handle the error... but the streams are still open!
    }
    finally {
        //close input
        if (mInputStream != null) {
            try {
                mInputStream.close();
            }
            catch(IOException ioex) {
                //Very bad things just happened... handle it
            }
        }
        //Close output
        if (mOutputStream != null) {
            try {
                mOutputStream.close();
            }
            catch(IOException ioex) {
                //Very bad things just happened... handle it
            }
        }
    }

如果您使用的是Java 8+,则不需要任何try/catch/finally噪音。您可以使用try-with-resources语法,Java会在您离开块时自动关闭资源:

    try(InputStream mInputStream = new FileInputStream("\\Path\\MyFileName1.txt")) {
        try(OutputStream mOutputStream = new FileOutputStream("\\Path\\MyFileName2.txt")) {
        //... do stuff to your streams
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接