由于网络传输存在着传输速度,传输路径等问题,将一个文件分为若干块来传送,可以提高传输效率,JAVA多线程技术正是将一个任务分为若干个任务来同时完成. 该实例应用JAVA多线程技术,将一个网络文件分为若干块,每一个线程负责一块数据的下载,下载完毕后将其保存在指定的磁盘路径中. 首先创建继承Thread类的传输文件线程类,其JAVA文件名为SiteFileFetch.java,代码如下: view plaincopy to clipboardprint?
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();
}
}
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 view plaincopy to clipboardprint?
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;
}
}
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 view plaincopy to clipboardprint?
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;
}
}
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 view plaincopy to clipboardprint?
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;
}
}
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 view plaincopy to clipboardprint?
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);
}
}
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 view plaincopy to clipboardprint?
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();
}
}
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)完成与服务器连接 view plaincopy to clipboardprint?
URL url=new URL("下载文件url地址和文件名");
HttpURLConnection httpConnection=(HttpURLConnection)url.openConnection();
URL url=new URL("下载文件url地址和文件名");
HttpURLConnection httpConnection=(HttpURLConnection)url.openConnection();(2)设置与服务器连接属性,即请求连接服务器信息 view plaincopy to clipboardprint?
httpConnection.setRequestProperty("User-Agent","NetFox");
httpConnection.setRequestProperty("User-Agent","NetFox");(3)设置下载文件的开始位置 view plaincopy to clipboardprint?
httpConnection.setRequestProperty("RANGE","bytes=0");
httpConnection.setRequestProperty("RANGE","bytes=0");(4)创建输入流,以输入流形式下载文件 view plaincopy to clipboardprint?
InputStream input=httpConnection.getInputStream();
InputStream input=httpConnection.getInputStream();(5)创建随机访问文件对象 view plaincopy to clipboardprint?
RandomAccess oSavedFile=new RandomAccessFile("java.zip","rw");
RandomAccess oSavedFile=new RandomAccessFile("java.zip","rw");(6)设置保存文件指针 view plaincopy to clipboardprint?
oSavedFile.seek(nPos);
oSavedFile.seek(nPos);(7)保存文件 view plaincopy to clipboardprint?
byte[] b=new byte[1024];
int nRead;
while((nRead=input.read(b,0,1024))>0){
oSavedFile.write(b,0,nRead);
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kuyesuifeng/archive/2008/06/27/2591972.aspx
posted on 2010-05-09 22:12
fly 阅读(418)
评论(0) 编辑 收藏 所属分类:
java学习