Which resources should be closed?

den*_*isp 5 java file download

我正在尝试从URL下载文件。有很多资源,我不知道需要关闭哪一个资源,还是我只需要关闭所有资源?

    public void downloadUpdate(final String url) {
    try {

        /* Which of these resources do I need to close? */
        final InputStream inputStream = new URL(url).openStream();
        final ReadableByteChannel readableByteChannel = Channels.newChannel(inputStream);
        final FileOutputStream fileOutputStream = new FileOutputStream(Bukkit.getServer().getUpdateFolderFile());
        final FileChannel fileChannel = fileOutputStream.getChannel();

        /* Downloading the update... */
        fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);

    } catch (final IOException exception) {
        exception.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

Sla*_*law 3

在您的情况下,可能唯一需要关闭的资源是InputStreamFileOutputStream。但是,为什么不直接使用 try-with-resources 来关闭它们呢?Closeable#close()以防万一,打电话也没什么坏处。事实上,您可能应该在完成它们后关闭Closeable您控件中的每个控件(即您打开的控件)(您不一定知道包装器是否也需要释放资源)。

try (InputStream inputStream = new URL(url).openStream();
     ReadableByteChannel readableByteChannel = Channels.newChannel(inputStream);
     FileOutputStream fileOutputStream = new FileOutputStream(Bukkit.getServer().getUpdateFolderFile());
     FileChannel fileChannel = fileOutputStream.getChannel()) {

    fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);

} catch (IOException ex) {
    ex.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

上面的内容与您现在拥有的没有太大不同。


1.Closeable#close()如果之前调用过,则调用该方法无效。AutoCloseable对于实现(不实现)来说不一定如此Closeable


另外,如果您使用 Java 9+,则不需要处理 NIO 通道。该类InputStream在 Java 9 中添加了一个方法:transferTo(OutputStream)

try (InputStream is = new URL(url).openStream();
     FileOutputStream fos = new FileOutputStream(...)) {
    is.transferTo(fos);
} catch (IOException ex) {
    ex.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

您也许还可以使用Files.copy(InputStream,Path,CopyOption...)(Java 7+)。

try (InputStream is = new URL(url).openStream()) {
    Path file = Bukkit.getServer().getUpdateFolderFile().toPath();
    Files.copy(is, file, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
    ex.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

请注意,这可能不会导致与使用时相同的行为FileOutputStream。我不完全确定是否FileOutputStream#<init>(File)会截断任何现有字节,或者是否只是从头开始覆盖字节。

如果您更喜欢使用 NIO 通道,您可以FileChannel直接打开一个 viaFileChannel.open(Path,OpenOption...)而不是通过FileOutputStream. 正如我在上面的示例中所示,您可以使用将 a 转换File为 a 。PathFile#toPath()