我正在尝试从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();
}
}
答案 0 :(得分:3)
对于您来说, 需要关闭的唯一资源可能是InputStream
和FileOutputStream
。但是,为什么不简单地使用try-with-resources将它们全部关闭呢?以防万一 1 调用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();
}
以上内容与您目前所拥有的并没有太大区别。
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();
}
您也许还可以使用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();
}
请注意,这可能导致与使用FileOutputStream
时不同的行为。我不确定FileOutputStream#<init>(File)
是否会截断任何现有字节,还是只是从头开始覆盖字节。
如果您更喜欢使用NIO通道,则可以直接通过FileChannel.open(Path,OpenOption...)
打开FileChannel
,而不用通过FileOutputStream
。如上例所示,您可以使用File
将Path
转换为File#toPath()
。
答案 1 :(得分:0)
对于您来说,关闭FileChannel
应该足够了,它将关闭parent
或相应资源的FileDescriptor(请参阅java11 sources)。实际上,以相同的结果,您只能关闭fileOutputStream
,它也将释放所有文件资源(source code)
但是,由于您依赖于这些可关闭资源的实现,因此最佳实践是关闭您打开的每个资源,更简单的方法是使用{{3 }}。
答案 2 :(得分:0)
谢谢大家,因为我使用的是Java 8,所以我可能要使用Files.copy(InputStream输入,Path目标,CopyOption ...选项),然后关闭InputStream。否则我会用InputStream#transferTo(OutputStream out)。