Я читаю книгу о параллельности 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
Сломанное изображение: https://imgur.com/UrgafA5