尊敬的前辈您好:)
我的目标:通过使用 Java 中的多线程,在给定 URL 的情况下下载 URL 资源,即将单个文件下载为多个部分(很像 IDM 的做法)并在结束时下载下载,将它们全部合并为 1 个最终文件。例如,如果图像大小为 260KB,我想将其下载到 2 个线程中,其中 1st Thread
应从 0KB 下载到 130KB & 2nd Thread
应从 131KB 到 260KB
下载。
技术使用: Java、RandomAccessFile、多线程、InputStreams
问题:此代码适用于 1 个线程,即,如果我运行从 0 到 260KB 的单个线程。但是当我尝试分块下载它时,出现以下错误:
它将下载额外的垃圾KB,即对于260KB的文件,将下载300+KB。
或
有时会下载确切的 260KB,但文件已损坏,我无法打开图像。
请帮助我。整整一周以来我已经尝试了很多,但我似乎无法理解这个问题。
初始代码
void InitiaeDownload
{
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
uc.connect();
long fileSize = uc.getContentLengthLong();
System.out.println("File Size = "+ fileSize );
uc.disconnect();
//------------------
long chunkSize = (long) Math.ceil(fileSize/2);
long startFrom = 0;
long endRange = (startFrom + chunkSize) - 1;
System.out.println("Chunk Size = " + chunkSize);
System.out.println("Part 1 :: Start = " + startFrom + "\tEnd To = " + endRange);
Thread t1 = new MyThread(url, file, startFrom, endRange);
t1.start();
startFrom += chunkSize;
long temp = endRange + chunkSize;
endRange = temp + (fileSize-temp); //also add remaining bytes
System.out.println("Part 2 :: Start = " + startFrom + "\tEnd To = " + endRange );
Thread t2 = new MyThread(url, file, startFrom, endRange);
t2.start();
}
现在,
线程类别
class MyThread extends Thread {
private URL url;
private long startFrom;
private long range;
private InputStream inStream;
private RandomAccessFile file;
public MyThread(URL url, RandomAccessFile file, long startFrom, long range) //parameterized constructor
{
this.url = url;
this.file = file;
this.startFrom = startFrom;
this.range = range;
}
public void run() {
System.out.println("Thread Running..");
Thread.currentThread().setPriority(MAX_PRIORITY);
System.setProperty("http.proxyHost", "192.168.10.50");
System.setProperty("http.proxyPort", "8080");
HttpURLConnection uc = null;
try {
uc = (HttpURLConnection) url.openConnection();
uc.setRequestProperty("Range", "bytes="+startFrom+"-"+range);
uc.connect();
inStream = uc.getInputStream();
System.out.println("Starting Download");
int bytesRead = 0;
byte[] buffer = new byte[ (int) (range-startFrom) ];
file.seek(startFrom); //adjusted start of file
while( (bytesRead = inStream.read(buffer) ) != -1 ) {
file.write(buffer, 0, bytesRead);
}
System.err.println("Download Completed!");
uc.disconnect();
}
catch(IOException e) {
System.err.println("Exception in " + Thread.currentThread().getName() + "\t Exception = " + e );
}
} ///END OF run()
} ////END OF MyThread Class
最佳答案
您正尝试从多个线程写入同一个file
对象。当您查找()或写入()时,它只有一个执行此操作的 View 。
如果您想同时在不同的位置写入相同的内容,每个线程都必须拥有自己的 RandomAccessFile 对象,即使它们都指向同一个底层文件。
顺便说一句:更改 IO 绑定(bind)进程的线程优先级可能起的作用很小(除非您是管理员,否则什么也做不了)
关于java - 使用 RandomAccessFile 在 Java 中通过多线程下载不正确的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22742617/