多线程技术下载文件

       由于网络传输存在着传输速度,传输路径等问题,将一个文件分为若干块来传送,可以提高传输效率,JAVA多线程技术正是将一个任务分为若干个任务来同时完成.        该实例应用JAVA多线程技术,将一个网络文件分为若干块,每一个线程负责一块数据的下载,下载完毕后将其保存在指定的磁盘路径中.         首先创建继承Thread类的传输文件线程类,其JAVA文件名为SiteFileFetch.java,代码如下:
import java.io.*;

import java.net.*;



public class SiteFileFetch extends Thread {		//传输文件线程类

	SiteInfoBean siteInfoBean=null;					//创建文件信息实例

	long [] nPos;									//文件位置指针

	long [] nStartPos;								//开始位置

	long [] nEndPos;								//结束位置

	FileSplitterFetch [] fileSplitterFetch;			//子线程对象

	long nFileLength;								//文件长度

	boolean bFirst=true;							//是否第一次读取

	boolean bStop=false;							//停止标志

	File tmpFile;									//文件传输临时信息

	DataOutputStream output;						//输出到文件的输出流

	public SiteFileFetch(SiteInfoBean bean) throws IOException{

		siteInfoBean=bean;

		tmpFile= new File(bean.getSFilePath()+File.separator+bean.getSFileName()+".info");

		if(tmpFile.exists()){

			bFirst=false;

			read_nPos();

		}

		else{

			nStartPos=new long[bean.getNSplitter()];

			nEndPos=new long[bean.getNSplitter()];

		}

	}

	public void run(){

		try{

			if(bFirst){

				nFileLength=getFileSize();				//获得文件长度

				if(nFileLength==-1){

					System.err.println("File Length is not known");

				}

				else 

					if(nFileLength==-2){

						System.err.println("File is not access!");

					}

					else{

						for(int i=0;i<nStartPos.length;i++){			//分割下载文件

							nStartPos[i]=(long)(i*(nFileLength/nStartPos.length));

						}

						for(int i=0;i<nEndPos.length-1;i++){

							nEndPos[i]=nStartPos[i+1];

						}

						nEndPos[nEndPos.length-1]=nFileLength;

					}

			}

			fileSplitterFetch=new FileSplitterFetch[nStartPos.length];				//创建FileSplitterFetch类实例

			for(int i=0;i<nStartPos.length;i++){					//启动FileSplitterFetch线程

				fileSplitterFetch[i]=new FileSplitterFetch(siteInfoBean.getSSiteURL(),siteInfoBean.getSFilePath()+File.separator+siteInfoBean.getSFileName(),nStartPos[i],nEndPos[i],i);

				Utility.log("Thread "+i+",nStartPos="+nStartPos[i]+" ,nEndPos= "+nEndPos[i]);

				fileSplitterFetch[i].start();

			}

			boolean breakWhile=false;

			while(!bStop){					//等待子线程结束

				write_nPos();

				Utility.sleep(500);

				breakWhile=true;

				for(int i=0;i<nStartPos.length;i++){

					if(!fileSplitterFetch[i].bDownOver){			//等待子线程返回

						breakWhile=false;

						break;

					}

				}

				if(breakWhile)				//是否结束while循环

					break;

			}

			System.out.println("文件传输结束!");

		}

		catch(Exception e){

			e.printStackTrace();

		}

	}

	

	public long getFileSize(){				//获得文件长度

		int nFileLength=-1;

		try{				//创建与WEB服务器的连接

			URL url=new URL(siteInfoBean.getSSiteURL());

			HttpURLConnection httpConnection=(HttpURLConnection)url.openConnection();

			httpConnection.setRequestProperty("User-Agent", "NetFox");

			int responseCode=httpConnection.getResponseCode();

			if(responseCode>=400){

				processErrorCode(responseCode);

				return -2;				//-2为WEB服务器响应错误

			}

			String sHeader;

			for(int i=1;;i++){

				sHeader=httpConnection.getHeaderFieldKey(i);

				if(sHeader!=null){

					if(sHeader.equals("Content-Length")){

						nFileLength=Integer.parseInt(httpConnection.getHeaderField(sHeader));

						break;

					}

				}

				else

					break;

			}

		}

		catch(IOException e){

			e.printStackTrace();

		}

		catch(Exception e){

			e.printStackTrace();

		}

		Utility.log(nFileLength);

		return nFileLength;

	}

	

	private void write_nPos(){					//保存传输文件指针位置

		try{

			output=new DataOutputStream(new FileOutputStream(tmpFile));

			output.writeInt(nStartPos.length);

			for(int i=0;i<nStartPos.length;i++){

				output.writeLong(fileSplitterFetch[i].nStartPos);

				output.writeLong(fileSplitterFetch[i].nEndPos);

			}

			output.close();

		}

		catch(IOException e){e.printStackTrace();}

		catch(Exception e) {e.printStackTrace();}

	}

	

	private void read_nPos(){				//读取保存的下载文件指针位置

		try{

			DataInputStream input=new DataInputStream(new FileInputStream(tmpFile));

			int nCount=input.readInt();

			nStartPos=new long[nCount];

			nEndPos=new long[nCount];

			for(int i=0;i<nStartPos.length;i++){

				nStartPos[i]=input.readLong();

				nEndPos[i]=input.readLong();

			}

			input.close();

		}

		catch(IOException e){e.printStackTrace();}

		catch(Exception e) {e.printStackTrace();}

	}

	

	private void processErrorCode(int nErrorCode){

		System.err.println("Error Code: "+nErrorCode);

	}

	

	public  void siteStop(){

		bStop=true;

		for(int i=0;i<nStartPos.length;i++)

			fileSplitterFetch[i].splitterStop();

	}

}
创建继承Thread类的将要传输的网络文件分割线程类,文件名为FileSplitterFetch.java
import java.io.*;

import java.net.*;



public class FileSplitterFetch extends Thread {

	String sURL;								//定义文件传输时使用的变量

	long nStartPos;								//分段文件传输开始位置

	long nEndPos;								//分段文件传输结束位置

	int nThreadID;								//子线程ID

	boolean bDownOver=false;					//完成文件传输

	boolean bStop=false;						//停止文件传输

	FileAccess fileAccess=null;					

	

	public FileSplitterFetch(String sURL,String sName,long nStart,long nEnd,int id) throws IOException{

		this.sURL=sURL;

		this.nStartPos=nStart;

		this.nEndPos=nEnd;

		nThreadID=id;

		fileAccess=new FileAccess(sName,nStartPos);			//创建文件并打开

	}

	

	public void run(){

		while(nStartPos<nEndPos && !bStop){

			try{									//创建连接

				URL url=new URL(sURL);

				HttpURLConnection httpConnection=(HttpURLConnection)url.openConnection();

				httpConnection.setRequestProperty("User-Agent", "NextFox");

				String sProperty="bytes= "+nStartPos+"-";

				httpConnection.setRequestProperty("RANGE", sProperty);

				Utility.log(sProperty);

				InputStream input=httpConnection.getInputStream();			//创建输入流对象

				byte[] b=new byte[1024];

				int nRead;

				while((nRead=input.read(b,0,1024))>0 && nStartPos<nEndPos && !bStop){

					nStartPos+=fileAccess.write(b,0,nRead);

				}

				Utility.log("Thread "+nThreadID + "is over!");

				bDownOver=true;

			}

			catch(Exception e){

				e.printStackTrace();

			}

		}

		

		

	}

	

	public void logResponseHead(HttpURLConnection con){			//处理和响应服务器头数据

		for(int i=1;;i++){

			String header=con.getHeaderFieldKey(i);

			if(header!=null)

				Utility.log(header+" : "+con.getHeaderField(header));

			else 

				break;

		}

	}

	

	public void splitterStop(){

		bStop=true;

	}

}
创建设置和获取网络信息类,类名为SiteInfoBean.java
public class SiteInfoBean {			//定义获取和设置相关文件类信息

	private String sSiteURL;			//定义URL变量

	private String sFilePath;			//定义存文件路径变量

	private String sFileName;			//定义文件名变量

	private int nSplitter;				//定义传输文件计数器

	

	public SiteInfoBean(){

		this("","","",5);

	}

	

	public SiteInfoBean(String sURL,String sPath,String sName,int nSplitter){

		sSiteURL=sURL;

		sFilePath=sPath;

		sFileName=sName;

		this.nSplitter=nSplitter;

	}

	

	public String getSSiteURL(){

		return sSiteURL;

	}

	

	public void setSSiteURL(String value){

		sSiteURL=value;

	}

	

	public String getSFilePath(){

		return sFilePath;

	}

	

	public void setSFilePath(String value){

		sFilePath=value;

	}

	

	public String getSFileName(){

		return sFileName;

	}

	

	public void setSFileName(String value){

		sFileName=value;

	}

	

	public int getNSplitter(){

		return nSplitter;

	}

	

	public void setNSplitter(int nCount){

		nSplitter=nCount;

	}

}
创建保存获取的网络文件类,类名为FileAccess.java
import java.io.*;





public class FileAccess implements Serializable {		//定义文件访问类

	RandomAccessFile oSavedFile;

	long nPos;

	

	public FileAccess() throws IOException{

		this("",0);

	}

	

	public FileAccess(String sName,long nPos) throws IOException{

		oSavedFile=new RandomAccessFile(sName,"rw");

		this.nPos=nPos;

		oSavedFile.seek(nPos);

	}

	

	public synchronized int write(byte[] b,int nStart,int nLen){

		int n=-1;

		try{

			oSavedFile.write(b,nStart,nLen);

			n=nLen;

		}

		catch(IOException e){

			e.printStackTrace();

		}

		return n;

	}

}
创建在下载过程中应用的工具类,名为Utility.java
public class Utility {				//定义输出提示信息及线程sleep类

	public Utility(){

		

	}

	

	public static void sleep(int nSecond){

		try{

			Thread.sleep(nSecond);

		}

		catch(Exception e){

			e.printStackTrace();

		}

	}

	

	public static void log(String sMsg){

		System.out.println(sMsg);

	}

	

	public static void log(int sMsg){

		System.out.println(sMsg);

	}

}

创建包含main()方法的测试类,文件名为TestMethod.java
public class TestMethod {

	private String sWebAddr="http://localhost:8080/java.zip";			//定义WEB地址和文件名

	private String sSavePath="d://temp";								//定义存文件路径

	private String sSaveName="java.zip";								//定义文件名

	public TestMethod(){

		try{

			SiteInfoBean bean=new SiteInfoBean(sWebAddr,sSavePath,sSaveName,5);

			SiteFileFetch fileFetch=new SiteFileFetch(bean);

			fileFetch.start();

		}

		catch(Exception e){

			e.printStackTrace();

		}

	}

	

	public static void main(String[] args){

		new TestMethod();

	}

}
以上六个类的功能为: SiteFileFetch类负责下载整个文件以及控制FileSplitterFetch类的线程 FileSplitterFetch类负责下载部分(一块)文件 SiteInfoBean类提供下载整个文件所需要的信息,例如文件保存目录,文件名和下载文件的URL等信息 FileAccess类负责文件的存储 Utility为工具类,提供下载文件时所使用的方法 TestMethod类为测试类,执行该实例程序入口 在下载文件过程中,主要应用方法有: (1)完成与服务器连接
URL    url=new   URL("下载文件url地址和文件名");

HttpURLConnection   httpConnection=(HttpURLConnection)url.openConnection();
(2)设置与服务器连接属性,即请求连接服务器信息
httpConnection.setRequestProperty("User-Agent","NetFox");
(3)设置下载文件的开始位置
httpConnection.setRequestProperty("RANGE","bytes=0");
(4)创建输入流,以输入流形式下载文件
InputStream input=httpConnection.getInputStream();
(5)创建随机访问文件对象
RandomAccess  oSavedFile=new RandomAccessFile("java.zip","rw");
(6)设置保存文件指针
oSavedFile.seek(nPos);
(7)保存文件
byte[] b=new byte[1024];

int nRead;

while((nRead=input.read(b,0,1024))>0){

        oSavedFile.write(b,0,nRead);

}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值