0

我想使用 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());
}
4

3 回答 3

1

通常,InputStreamReaderBufferedReader类似的遵循包装器样式模式,它们在 上关闭底层流close

但是,在某些情况下,这两种方法并不相同。如果外部包装器在构造过程中可以抛出异常,那么内部资源将不会被关闭。

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

如果您使用@Xabster 的建议(源示例)并分别分配两种资源,这应该确保InputStream即使外部失败,内部也会关闭。

您绝对应该查看以下资源: http ://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

于 2014-07-30T19:49:28.667 回答
0

当调用它们的关闭时,流会关闭底层流,所以两者都很好。如果你需要匿名创建的 InputStreamReader 作为 try { } 范围内的变量名,但你不想要 2 个嵌套的 try { },你可以这样做:

try (InputStream is = urlConn.getInputStream(); InputStreamReader isr = new InputStreamReader(is)) {
于 2014-07-30T19:29:08.093 回答
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());
        }
    }
于 2020-08-25T04:14:10.343 回答