📄 downfile.java
字号:
package Tiff;
import java.awt.TextArea;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
class DownFileSplitter extends Thread {
String dlURL; // 定义文件传输时服务器的URL
long startPos; // 分段的开始位置
long endPos; // 分段的结束位置
int threadID; // 子线程ID
TextArea textArea = new TextArea();
boolean done = false; // 文件传输完成
boolean stop = false; // 文件传输被终止
RandomAccessFile file;
public DownFileSplitter(String dlURL,String saveAs,long nStart,long nEnd,int id,TextArea textArea) throws IOException{
this.dlURL = dlURL;
this.startPos = nStart;
this.endPos = nEnd;
threadID = id;
this.textArea = textArea;
file = new RandomAccessFile(saveAs,"rw");
file.seek(startPos);
}
public void run()
{
while(startPos < endPos && !stop)
{
try{
URL url = new URL(dlURL);
HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection ();
String sProperty = "bytes="+startPos+"-";
httpConnection.setRequestProperty("RANGE",sProperty);//请求传输的开始位置
System.out.println("线程" + threadID + " 下载文件......请等待" );
textArea.append("\n线程" + threadID + "下载文件......请等待");
InputStream input = httpConnection.getInputStream();
byte[] b = new byte[1024];
int offset;
offset = (int)endPos - (int)startPos;
if(offset>1024) offset = 1024;
while(input.read(b,0,offset)> 0 && startPos < endPos && !stop)
{
offset = (int)endPos - (int)startPos;
if(offset>1024) offset = 1024;
System.out.println("started " + startPos + " offset: " + offset);
file.write(b,0,offset);
startPos += offset;//下一次开始写的位置
}
System.out.println("线程 " + threadID + " 下载完毕!!");
done = true;
textArea.append("\n线程" + threadID + " 下载完毕!");
file.close();
}
catch(Exception e)
{
e.printStackTrace ();
}
}
}
public void splitterStop()
{
stop = true;
}
}
//the second class
public class DownFile extends Thread // 传输文件线程类
{
String dlURL;
String saveFileAs;
int nthread;
String info = new String();
TextArea textArea = new TextArea();
long[] position;
long[] startPos; //开始位置
long[] endPos; //结束位置
DownFileSplitter[] downFileSplitter; //子线程对象,数组形式
long fileLength; //文件长度
boolean stop = false; //停止标志
DataOutputStream output; //输出到文件的输出流
public DownFile(String sURL,String saveFileAs,int nthread,TextArea textArea) throws IOException
{
this.dlURL = sURL;
this.saveFileAs = saveFileAs;
this.nthread = nthread;
this.textArea = textArea;
startPos = new long[nthread];//各个线程的开始位置,每个数组元素都是一个位置标志
endPos = new long[nthread];//各个线程的结束位置
}
public void run(){
info = "目标文件: " + dlURL;
System.out.println(info);
textArea.append("\n" + info);
info = "文件存为: " + saveFileAs;
System.out.println(info);
textArea.append("\n" + info);
info = "\n线程总数: " + nthread;
System.out.println(info);
textArea.append("\n" + info);
try{
fileLength = getFileSize();
if(fileLength == -1){
System.err.println("不可知的文件长度!");
textArea.append("\n不可知的文件长度");
}
else
if(fileLength == -2){
System.err.println("文件无法获取!");
textArea.append("\n文件无法获取");
}
else{
for(int i=0;i<startPos.length;i++){//文件划分成和进程数相同的小块,这里是五块.
startPos[i] = (long)(i*(fileLength/startPos.length));
}
for(int i=0;i<endPos.length-1;i++){
endPos[i] = startPos[i+1];
}
endPos[endPos.length-1] = fileLength;
for(int i=0;i<startPos.length;i++){
info = "线程" + i + " 下载范围: " + startPos[i] + " -- " +endPos[i];
System.out.println(info);
textArea.append("\n" + info);
}
}
downFileSplitter = new DownFileSplitter[startPos.length];//启动一组子线程数组,起始位置为 downFileSplitter
for(int i=0;i<startPos.length;i++){
downFileSplitter[i] = new DownFileSplitter(dlURL,saveFileAs,startPos[i],endPos[i],i,textArea);
info = "线程" + i + " 启动";
textArea.append("\n" + info);
downFileSplitter[i].start();
System.out.println(info);
}
boolean breakWhile = false;
while(!stop)
{//等待整个下下载过程结束
Thread.sleep(500);
breakWhile = true;
for(int i=0;i<startPos.length;i++){//检测每条线程都已经完成,则整个下载完成
if(!downFileSplitter[i].done){//if not done,continue
breakWhile = false;
break;
}
}
if(breakWhile)
break;
}//直到每条线程都已经完成了.
System.out.println("文件传输结束!");//文件传输结束
textArea.append("\n文件传输结束!");
}
catch(Exception e){
e.printStackTrace ();
}
}
public long getFileSize(){//获得文件长度
int fileLength = -1;
try{
URL url = new URL(dlURL);
HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection ();
int responseCode=httpConnection.getResponseCode();
if(responseCode>=400){
processErrorCode(responseCode);
return -2; //Web服务器响应错误
}
String sHeader;
for(int i=1;;i++){//查找标识文件长度的文件头,获取文件长度
sHeader=httpConnection.getHeaderFieldKey(i);
if(sHeader!=null){
if(sHeader.equals("Content-Length")){
fileLength = Integer.parseInt(httpConnection.getHeaderField(sHeader));
break;
}
}
else
break;
}
}
catch(IOException e){e.printStackTrace ();}
catch(Exception e){e.printStackTrace ();}
return fileLength;
}
private void processErrorCode(int nErrorCode){
System.err.println("Error Code : " + nErrorCode);
}
//停止文件传输
public void siteStop(){
stop = true;
for(int i=0;i<startPos.length;i++)
downFileSplitter[i].splitterStop();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -