从URL更有效地下载图像

时间:2011-07-21 22:01:02

标签: java download

情况:我有一个ArrayList<String>包含一堆图像链接(http:/www.foo.com/bar/image1.jpg,http://www.foo.com/bar/image2.png ,...等)

我找到了一段代码,以便逐一下载:

public void run() {
        try {
            int counter = 1;
            for (String image : imagesList) {
                controller.setDownloadStatusTextArea("Downloading image " + counter + " of " + imagesList.size());
                URL u = new URL(image);
                URLConnection uc = u.openConnection();
                String contentType = uc.getContentType();
                int contentLength = uc.getContentLength();
                InputStream raw = uc.getInputStream();
                InputStream in = new BufferedInputStream(raw);
                byte[] data = new byte[contentLength];
                int bytesRead;
                int offset = 0;
                while (offset < contentLength) {
                    bytesRead = in.read(data, offset, data.length - offset);
                    if (bytesRead == -1)
                        break;
                    offset += bytesRead;
                }
                in.close();
                if (offset != contentLength) {
                    throw new IOException("Only read " + offset + " bytes; Expected " + contentLength + " bytes");
                }
                String[] tmp = image.split("/");
                String filename = tmp[tmp.length - 1];
                FileOutputStream out = new FileOutputStream(filename);
                out.write(data);
                out.flush();
                out.close();
                counter++;
            }
            controller.setDownloadStatusTextArea("Download complete");
        } catch (Exception ex) {
            controller.setDownloadStatusTextArea("Download failed");
        }
    }

这是我第一次在Java中做这样的事情,我觉得通过在for循环之外移动一堆变量可以更有效地使用这些代码。但我不确定哪个可以安全地移到外面而不影响功能和/或性能(无论是消极的还是积极的)。我们将非常感谢对这种情况的见解。 另外:我可以指定需要下载文件的位置吗?现在它们只出现在项目文件夹中,我希望用户能够更改他的下载文件夹。

提前致谢。

3 个答案:

答案 0 :(得分:4)

此代码不能更加节省时间。

以这种方式思考:即使你把每一个可有可无的操作码都抛光了,JVM执行这部分代码所花费的时间也不重要。真正的延迟将是等待数据通过网络到达。

它可能更节省空间,但我认为没有必要。

编辑:您可以做的是使用线程同时下载多张图片。如果上面的代码看起来很复杂,我会反对它:花一些时间来学习你的语言。

答案 1 :(得分:2)

您不需要为整个图像分配一个字节数组...您只需要一个小缓冲区 - 例如8 kB。 然后,从连接读取8 kB,并在循环中写入FileOutputStream。

为了使整个代码更简单(踢出循环),你可以使用例如 Commons-IO (点击FRAMES链接查看整个javadoc)。

答案 2 :(得分:1)

在允许用户选择目录的Swing应用程序中,使用JFileChooser实例化setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)

只要确保每次迭代都正确初始化,就可以将所有变量声明移到循环之外。相对于下载和保存文件所需的时间,您不会节省大量时间。