下载到Java文件 - 非常慢

时间:2011-03-06 07:16:49

标签: java

给出以下示例代码:

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秒或更短的时间内下载。知道问题在这里吗?

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);