给出以下示例代码:
somefile = new URL("http://somefile.rar");
ReadableByteChannel rbc = Channels.newChannel(somefile.openStream());
FileOutputStream fos = new FileOutputStream("test");
long start = System.currentTimeMillis();
fos.getChannel().transferFrom(rbc, 0, 1 << 24);
long end = System.currentTimeMillis();
System.out.println(end-start);
有问题的文件是14MB。当我使用上面的代码下载它时,每次需要26-30秒。我注意到,从java下载时,有些时候根本没有传输字节。当我从浏览器下载相同的文件时,它会在4秒或更短的时间内下载。知道问题在这里吗?
答案 0 :(得分:3)
我从未见过这种下载方式。也许你应该试试BufferedInputStream
:
URL url = new URL("http://yourfile.rar");
File target = new File("package.rar");
try (BufferedInputStream bis = new BufferedInputStream(url.openStream())) {
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(target))) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
bos.flush();
}
}
答案 1 :(得分:1)
建议 - 为什么不尝试删除频道并仅使用流。例如,您可以使用commons-io
IOUtils.copy(new BufferedInputStream(somefile.openStream()),
new BufferedOutputStream(fos));
// of course, you'd have to close the streams at the end.
答案 2 :(得分:1)
使用频道是一个不错的主意,因为您可以通过这种方式避免在内存中多余的数据复制。但是你在这里使用的不是一个真正的套接字通道,而是来自你的URL的InputStream周围的包装器通道,这会破坏你的体验。
您可以使用SocketChannel自己实现HTTP协议,或者找到允许此功能的库。 (但是,如果使用chunked-encoding发送结果,你仍然需要自己解析它。)
因此,更简单的方法是使用其他答案给出的通常的流复制方式。
答案 3 :(得分:0)
使用common-io下载文件的更好方法:
FileUtils.copyUrlToFile(URL url, String destination);