Downloading images from URL more efficiently
Situation: I have an ArrayList<String>
containing a bunch of links to images (http:/www.foo.com/bar/image1.jpg, http:/www.foo.com/bar/image2.png,... etc)
I have found a working piece of code in order to download them one by one:
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 offse开发者_如何转开发t = 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");
}
}
This is the first time I'm doing something like this in Java, and I have a feeling this code can be much more efficient by moving a bunch of variables outside of the for loop. But I'm not sure which can be safely moved outside without affecting the functionality and/or performance (both in a negative or positive way). An insight in this situation would be greatly appreciated. Also: Can I specify where the files need to be downloaded to? Now they just appear in the project folder, I want the user to be able to change his download folder.
Thanks in advance.
This code can't be made much more time-efficient.
Think of it this way: even if you polished every last dispensable opcode out it, the time it takes for the JVM to execute this portion of code is not significant at all. The real delay will be in waiting for the data to arrive through the network.
It could be more space-efficient, but I don't think it's necessary.
Edit: what you can do is download multiple images at the same time, using threads. If the code above looks complicated though, I would advise against it: take some more time to learn your way around the language.
You don't need to allocte a byte array for whole image... you only need a small buffer - e.g. 8 kB. Then, read 8 kB from the connection, and write into the FileOutputStream, in a loop.
To make whole code simpler (kick out the loops), you can use e.g. Commons-IO (click on FRAMES link to see whole javadoc).
In a Swing application to let the user select a directory, instantiate a JFileChooser
with setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
.
You could move all the variable declarations outside of the loop as long as you ensure they are properly initialized with each iteration. You won't save a lot of time relative to the time it will take to download and save the file though.
精彩评论