您的位置:首页 > 编程语言 > Java开发

使用RandomAccessFile实现多线程下载

2017-05-27 12:03 337 查看
使用写流来下载网上的资源,用多线程对资源进行下载。

     第一步:创建两个java脚本,一个服务器,一个客户端

首先推出多线程下载的实现原理



  第二步:服务器部分   继承  Thread 

            1、定义四个变量(线程id、文件下载的路径、文件保存的路径、单个线程下载的数据量)

public int id;//线程id
public URL url;//文件下载的路径
public File file;//文件保存的路径
public int singleThreadNum;//单个线程下载的数据量
             2、定义构造方法

public DownThread(int id, URL url, File file, int singleThreadNum) {
this.id = id;
this.url = url;
this.file = file;
this.singleThreadNum = singleThreadNum;
}
              3、实现run方法

@Override
public void run() {

}
                4、在run方法中实例化RandomAccessFile随机读写类,参数中放入file文件以及"rwf";

@Override
public void run() {
RandomAccessFile raf=new RandomAccessFile(file, "rwd");
}


             5、开始计算每个线程下载的开始位置与结束位置

int start=id*singleThreadNum;
int end=(id+1)*singleThreadNum;


            6、通过从客户端传递过来的URL获取下载的链接,url是在客户端中调用构造方法后传到服务器的值,然后打开链接
      HttpURLConnection conn=(HttpURLConnection) url.openConnection();
            7、设置传递数据的超时时间,ReadTimeout当网络不正常的时候起作用
conn.setReadTimeout(5000);
             8、设置一般请求属性,参数是规定的写法,放的是开始位置和结束位置,它会自动给你计算出结果
conn.setRequestProperty("Range", "bytes="+start+"-"+end);
             9、然后就是一个读的操作,首先需要判断局部请求是否反应成功,状态码是206
if(conn.getResponseCode()==206){
//这里需要用到数据定位的方法seek
raf.seek(start);
//获取输入流
InputStream is=conn.getInputStream();
byte bytes[]=new byte[1024];
int len=0;
while((len-is.read(bytes,0,bytes.length))!=-1){
raf.write(bytes,0,len);
}
raf.close();
is.close();
}
服务器代码

package com.bihua.test;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

public class DownThread extends Thread{
public int id;//线程id
public URL url;//文件下载的路径
public File file;//文件保存的路径
public int singleThreadNum;//单个线程下载的数据量
public DownThread(int id, URL url, File file, int singleThreadNum) {
this.id = id;
this.url = url;
this.file = file;
this.singleThreadNum = singleThreadNum;
}
@Override public void run() {try {
RandomAccessFile raf=new RandomAccessFile(file, "rwd");
//分别计算每个下载的开始位置和结束位置
int start=id*singleThreadNum;
int end=(id+1)*singleThreadNum;
//通过传过来的URL获取下载的链接
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
//设置下载超时值,是传递数据的超时时间。当网络不正常时,ReadTimeout才真正的起作用
conn.setReadTimeout(5000);
//设置一般请求属性
conn.setRequestProperty("Range", "bytes="+start+"-"+end);
//局部请求 状态码为206
if(conn.getResponseCode()==206){
raf.seek(start);
//获取输入流
InputStream is=conn.getInputStream();
byte bytes[]=new byte[1024];
int len=0;
while((len-is.read(bytes,0,bytes.length))!=-1){
raf.write(bytes,0,len);
}
raf.close();
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}


客户端:
package com.zking.test;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

public class TestDowm {
public static void main(String[] args) {
//设置线程数
int threadNum=50;
//路径放你要从哪个网站进行下载,放地址栏的路径
               String path="路径";
//httpUrlConnection
try {
//获取下载地址
URL url=new URL(path);
//通过下载地址打开连接
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
//设定请求方式
conn.setRequestMethod("GET");
//判断响应码是否为200  只有200的时候才会进入这个网页
if(conn.getResponseCode()==200){
//获取服务器中文件的大小
int length=conn.getContentLength();
//保存的文件路径
File f=new File(路径);
//对随机的文件进行读写
RandomAccessFile raf=new RandomAccessFile(f, "rw");
//设置下载文件大小
raf.seek(length);
raf.close();
//每个线程下载的数据量
int singleThreadNum=length%threadNum==0?length/threadNum:length/threadNum+1;
for (int i = 0; i < threadNum; i++) {
new DownThread(i, url, f, singleThreadNum).start();
}
}else{
System.out.println("网页错误");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}


多线程的下载就整理到这里,如有不懂的地方可以进行评论或者私信我,欢迎同道之人指点一二!

   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息