在Java中有没有一种方法可以将一个文件以异步方式复制到另一个文件中?类似于 Stream.CopyToAsync 在C#中,我试图找到的是。
我试图实现的是从互联网上下载一系列约40个文件,这是我为每个文件想出的最佳方案。
CompletableFuture.allOf(myFiles.stream()
.map(file -> CompletableFuture.supplyAsync(() -> syncDownloadFile(file)))
.toArray(CompletableFuture[]::class))
.then(ignored -> doSomethingAfterAllDownloadsAreComplete());
在哪里 syncDownloadFile
是。
private void syncDownloadFile(MyFile file) {
try (InputStream is = file.mySourceUrl.openStream()) {
long actualSize = Files.copy(is, file.myDestinationNIOPath);
// size validation here
} catch (IOException e) {
throw new RuntimeException(e);
}
}
但这意味着我在任务执行者内部有一些阻塞调用,我想避免这种情况,这样我就不会同时阻塞太多的执行者。
我不知道C#方法内部是否也是这样做的(我的意思是,总得有东西在下载那个文件吧?)。
有没有更好的方法来完成这个任务?
AsynchronousFileChannel
(简称AFC)是在Java中用非阻塞IO管理Files的正确方法。遗憾的是,它没有提供一个基于承诺的(也就是作为 Task
(在.net中) API,如 CopyToAsync(Stream)
.Net的。
替代品 RxIo 库是建立在AFC之上的,并提供了? AsyncFiles
异步API的不同调用习惯:基于回调。CompletableFuture
(相当于.net Task
),也有反应式流。
例如,虽然可以异步地从一个文件复制到另一个文件。
Path in = Paths.get("input.txt");
Path out = Paths.get("output.txt");
AsyncFiles
.readAllBytes(in)
.thenCompose(bytes -> AsyncFiles.writeBytes(out, bytes))
.thenAccept(index -> /* invoked on completion */)
请注意,连续性是由一个线程从后台调用的。AsynchronousChannelGroup
.
因此,你可以使用一个非阻塞的HTTP客户端来解决你的问题,并使用 ComplableFuture
基于API与 AsyncFiles
用。例如,AHC是有效的选择。参见这里的用法。https:/github.comAsyncHttpClientasync-http-client#using-continuations。