情况:我有一个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循环之外移动一堆变量可以更有效地使用这些代码。但我不确定哪个可以安全地移到外面而不影响功能和/或性能(无论是消极的还是积极的)。我们将非常感谢对这种情况的见解。 另外:我可以指定需要下载文件的位置吗?现在它们只出现在项目文件夹中,我希望用户能够更改他的下载文件夹。
提前致谢。
答案 0 :(得分:4)
此代码不能更加节省时间。
以这种方式思考:即使你把每一个可有可无的操作码都抛光了,JVM执行这部分代码所花费的时间也不重要。真正的延迟将是等待数据通过网络到达。
它可能更节省空间,但我认为没有必要。
编辑:您可以做的是使用线程同时下载多张图片。如果上面的代码看起来很复杂,我会反对它:花一些时间来学习你的语言。
答案 1 :(得分:2)
您不需要为整个图像分配一个字节数组...您只需要一个小缓冲区 - 例如8 kB。 然后,从连接读取8 kB,并在循环中写入FileOutputStream。
为了使整个代码更简单(踢出循环),你可以使用例如 Commons-IO (点击FRAMES链接查看整个javadoc)。
答案 2 :(得分:1)
在允许用户选择目录的Swing应用程序中,使用JFileChooser
实例化setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
。
只要确保每次迭代都正确初始化,就可以将所有变量声明移到循环之外。相对于下载和保存文件所需的时间,您不会节省大量时间。