在Java中安全地关闭流

时间:2014-07-30 19:24:04

标签: java stream try-with-resources

我想安全地使用Java的try-with-resources完全关闭多个流。我不知道我有多啰嗦。我想确保我的资源完全被处理掉。我的代码是这样的:

JSONObject json;

URL url = new URL("http://example.com/api.json");
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
urlConn.setRequestMethod("GET");
urlConn.connect();
try (InputStream is = urlConn.getInputStream()) {
    try (InputStreamReader isr = new InputStreamReader(is)) {
        StringBuilder sb = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(isr)) {
            String inputStr;
            while ((inputStr = reader.readLine()) != null)
                sb.append(inputStr);

            json = new JSONObject(sb.toString());
        }
    }
}

我想知道这是否过度,如果我能做到这一点:

//...
urlConn.connect();

StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(
        new InputStreamReader(urlConn.getInputStream()))) {
    String inputStr;
    while ((inputStr = reader.readLine()) != null)
        sb.append(inputStr);

    json = new JSONObject(sb.toString());
}

3 个答案:

答案 0 :(得分:0)

Streams在调用close时关闭它们,所以两者都很好。如果您需要在try {}范围内将匿名创建的InputStreamReader作为变量名称,但您不想要2个嵌套的try {},则可以执行以下操作:

try (InputStream is = urlConn.getInputStream(); InputStreamReader isr = new InputStreamReader(is)) {

答案 1 :(得分:0)

通常,InputStreamReaderBufferedReader和类似关注包装器样式模式,它们关闭close上的基础流。

但有时这两种方法并不相同。如果外部包装器在构造期间可能抛出异常,那么内部资源将不会被关闭。

在您的示例中,对new InputStreamReader(...)的调用实际上可能会抛出错误(由于编码不受支持)。如果发生这种情况,那么通过InputStream方法创建的urlConn.getInputStream()将会悬空。

如果你使用@Xabster的提议(源代码示例)并且分别分配了两个资源,这应该确保内部InputStream关闭,即使外部的{{1}}失败。

您一定要查看以下资源: 的 http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

答案 2 :(得分:0)

对资源使用try时,资源会自动关闭。要自动关闭,必须在try中声明和初始化资源,如下所示。也可以在try内准备多个语句,如图所示。

String oldContent = "";

try(BufferedReader reader = new BufferedReader(new FileReader("filePath")); 
    FileWriter writer = new FileWriter("filePath")) {
        
        String line = reader.readLine();
        while (null != line) {
            oldContent = String.valueOf(oldContent) + line + System.lineSeparator();
            line = reader.readLine();
        }

        writer.write("filePath");

    } catch (IOException e) {
            LOG.error(e.getMessage());
        }
    }