我正在读一本关于java并发的书,其中有一个从互联网下载图像文件的例子。该程序使用Files.copy()内置函数下载图像文件。代码:
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.concurrent.TimeUnit;
public class TwoFileDownloadingWithJoin {
public static void main(String[] args) {
Thread beatPrinter = new BeatPrinter();
Thread down1 = new FileDownloader("https://secure.meetupstatic.com/photos/event/e/9/f/9/600_464039897.jpeg", "meet1.jpg");
Thread down2 = new FileDownloader("https://secure.meetupstatic.com/photos/event/2/d/0/f/600_464651535.jpeg", "meet2.jpg");
beatPrinter.setName("Beat Printer");
down1.setName("file1 downloader");
down2.setName("file2 downloader");
try {
down1.start();
down2.start();
TimeUnit.MILLISECONDS.sleep(100);
beatPrinter.start();
down1.join();
down2.join();
((BeatPrinter) beatPrinter).kill();
beatPrinter.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Download Complete");
}
}
class BeatPrinter extends Thread {
private volatile boolean live = true;
@Override
public void run() {
while (live) {
printStar("Downloading ");
}
}
void kill() {
live = false;
}
private void printStar(String msg) {
System.out.print(msg);
char[] signs = {'-', '\\', '|', '/'};
for (char s : signs) {
System.out.print(s);
try {
Thread.sleep(300);
System.out.print('\b');
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < msg.length(); i++)
System.out.print('\b');
}
}
class FileDownloader extends Thread {
private String url;
private String fileName;
FileDownloader(String url, String fileName) {
this.url = url;
this.fileName = fileName;
}
@Override
public void run() {
File destinationFile = new File(fileName);
try {
System.out.println("Starting download of " + fileName);
URL fileUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) fileUrl.openConnection();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream inputStream = connection.getInputStream();
Files.copy(inputStream, destinationFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
inputStream.close();
} else {
System.out.println("Error: " + connection.getResponseMessage());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
我已按如下方式修改程序以显示下载进度:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
public class TwoFileDownloadingWithJoin {
public static void main(String[] args) {
Thread down1 = new FileDownloader("https://secure.meetupstatic.com/photos/event/e/9/f/9/600_464039897.jpeg", "meet1.jpg");
Thread down2 = new FileDownloader("https://secure.meetupstatic.com/photos/event/2/d/0/f/600_464651535.jpeg", "meet2.jpg");
down1.setName("file1 downloader");
down2.setName("file2 downloader");
try {
down1.start();
down2.start();
TimeUnit.MILLISECONDS.sleep(100);
down1.join();
down2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Download Complete");
}
}
class FileDownloader extends Thread {
private String url;
private String fileName;
private double totRead;
private ProgressUpdater progressUpdater;
FileDownloader(String url, String fileName) {
this.url = url;
this.fileName = fileName;
this.progressUpdater = new ProgressUpdater(this, fileName);
}
double getTotRead() {
return totRead;
}
@Override
public void run() {
File destinationFile = new File(fileName);
try {
System.out.println("Starting download of " + fileName);
URL fileUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) fileUrl.openConnection();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
double fileSize = Double.parseDouble(connection.getHeaderField("content-length"));
InputStream fis = connection.getInputStream();
FileOutputStream fos = new FileOutputStream(destinationFile);
byte[] buffer = new byte[1024];
double currRead;
double totSize = fileSize / 1024.0;
progressUpdater.setTotSize(totSize);
progressUpdater.start();
while ((currRead = fis.read(buffer)) != -1) {
fos.write(buffer);
totRead += currRead / 1024;
}
fis.close();
fos.close();
progressUpdater.kill();
progressUpdater.join();
} else {
System.out.println("Error: " + connection.getResponseMessage());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ProgressUpdater extends Thread {
private FileDownloader fileDownloader;
private volatile boolean killed;
private String fileName;
private double totSize;
public ProgressUpdater(FileDownloader fileDownloader, String fileName) {
this.fileDownloader = fileDownloader;
this.fileName = fileName;
killed = false;
}
public void kill() {
killed = true;
}
public void setTotSize(double totSize) {
this.totSize = totSize;
}
@Override
public void run() {
boolean hundredPercent = false;
while (!killed || !hundredPercent) {
double totRead = fileDownloader.getTotRead();
System.out.println(String.format("%s: %.2fKB of %.2fKB downloaded(%.2f%%)", fileName, totRead, totSize, 100 * totRead / totSize));
hundredPercent = (100 * totRead / totSize) > 99.00;
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
我没有使用Files.copy(),而是从输入流中读取字节,然后将字节写入输出文件。但我的方法导致图像破碎。问题在哪里?
原始图片:https://secure.meetupstatic.com/photos/event/e/9/f/9/600_464039897.jpeg