多线程实现HTTP下载器(断点续传)_使用IO和线程知识
1.断点续传:
所谓的断点续传就是断点或者断网能够从该位置继续下载(使用IO)
每次下载文件时都在临时文件里写入已传位置,下载完成后删除临时文件
2.分片:
该功能不是很完善
把文件通过计算分成4片
然后使用多线程下载
3.判断线程池所有线程完成
见我上一篇博客(传送门):判断线程池所有线程完成
直接贴代码吧:
1.自定义线程类:
package 多线程下载器;import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DecimalFormat;public class MyDownLoadingThread implements Runnable {//获得分隔符private static String HH = System.getProperty("line.separator");//防止断网断电后文件重新下载使用临时文件保存下载进度private static String lsFile = "taget/ls.txt";//下载范围private long[] rangeAtoB = null;//HTTP地址private String STRURL = null;//保存文件名private String morenName = null;//最大字节数组长度private static int MAX=1024000;@Overridepublic void run() {// TODO Auto-generated method stubHttpURLConnection connection = null;try {URL url = new URL(STRURL);connection = (HttpURLConnection)url.openConnection();File file = new File(lsFile);if(file.exists()) {try(BufferedReader reader = new BufferedReader(new FileReader(file))){String line = null;while((line=reader.readLine())!=null) {if(line.charAt(0)==Thread.currentThread().getName().charAt(Thread.currentThread().getName().length()-1)) {rangeAtoB[0] = Long.valueOf(line.substring(line.indexOf(':')+1,line.indexOf('-')));rangeAtoB[1] = Long.valueOf(line.substring(line.indexOf('-')+1));break;}}}}connection.addRequestProperty("Range", "bytes="+rangeAtoB[0]+"-"+rangeAtoB[1]);connection.connect();if(connection.getResponseCode()/100!=2) {System.out.println("未连接成功!,退出");return;}else {System.out.println(Thread.currentThread().getName()+"连接成功!");}if(this.morenName==null) {this.morenName = STRURL.substring(STRURL.lastIndexOf('/')+1);}else {if(STRURL.indexOf('.')!=-1)this.morenName+=STRURL.substring(STRURL.lastIndexOf('.'));}DecimalFormat decimalFormat = new DecimalFormat("0.00");DecimalFormat format = new DecimalFormat("0.00%");int fileLength = connection.getContentLength();//文件长度System.out.printf("文件大小: %.2fMB\n",fileLength/1024.0/1024);long timeStart = System.currentTimeMillis();try(InputStream inputStream = connection.getInputStream();BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);RandomAccessFile accessFilec = new RandomAccessFile(new File("taget/"+this.morenName), "rw"); ){long sec =rangeAtoB[0];accessFilec.seek(sec);byte[] bs = null;int avg = 0;//计数循环了几次,来算平均下载速度double sum = 0;while(sec<rangeAtoB[1]) {long startTime = System.currentTimeMillis();if(sec+MAX>rangeAtoB[1]) {bs = new byte[(int) (rangeAtoB[1]-sec)];}else {bs = new byte[MAX];}for (int i = 0; i < bs.length; i++) {bs[i] = (byte) bufferedInputStream.read();}accessFilec.seek(sec);accessFilec.write(bs);writeLs(sec, rangeAtoB[1]);long endTime = System.currentTimeMillis();System.out.println(Thread.currentThread().getName()+"已下载: "+format.format(((double)sec-rangeAtoB[0])/(rangeAtoB[1]-rangeAtoB[0]))+",下载速度: "+decimalFormat.format((bs.length/1024.0/1024.0/((endTime-startTime)/1000.0)))+"MB/s");sec+=MAX;avg++;sum+=(bs.length/1024.0/1024.0/((endTime-startTime)/1000.0));}long timeEnd = System.currentTimeMillis();if((timeEnd-timeStart)/1000.0<60) {System.out.println(Thread.currentThread().getName()+" 已下载完成!您本次的平均下载速度是: "+decimalFormat.format(sum/avg)+"MB/s"+",耗时: "+(timeEnd-timeStart)/1000.0+"s");}else {System.out.println(Thread.currentThread().getName()+" 已下载完成!您本次的平均下载速度是: "+decimalFormat.format(sum/avg)+"MB/s"+",耗时: "+(timeEnd-timeStart)/1000.0/1000.0+"min");}} } catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** 写临时文件* @param 字节数组的起始位置* @param 字节数组的结束位置*/public synchronized void writeLs(long a,long b) {File file = new File(lsFile);if(file.exists()) {try( BufferedReader reader = new BufferedReader(new FileReader(file));){String line = null;StringBuffer buffer = new StringBuffer();while((line=reader.readLine())!=null) {if(line.charAt(0)==Thread.currentThread().getName().charAt(Thread.currentThread().getName().length()-1)) {buffer.append(Thread.currentThread().getName().substring(Thread.currentThread().getName().lastIndexOf('-')+1)+":"+String.valueOf(a)+"-"+String.valueOf(b)+HH);}else {buffer.append(line+HH);}}
// System.out.println(buffer.toString());BufferedWriter writer = new BufferedWriter(new FileWriter(lsFile,false));writer.write(buffer.toString());writer.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}else {//该文件不存在时初始化try(BufferedWriter writer = new BufferedWriter(new FileWriter(lsFile,false))){writer.write("1:0-0"+HH+"2:0-0"+HH+"3:0-0"+HH+"4:0-0");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}public MyDownLoadingThread() {}public MyDownLoadingThread(String URL,long[] rangeAtoB) {this.STRURL = URL;this.rangeAtoB = rangeAtoB;}public MyDownLoadingThread(String URL,String morenName,long[] rangeAtoB) {this.STRURL = URL;this.morenName = morenName;this.rangeAtoB = rangeAtoB;}}
2.服务类
package 多线程下载器;import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class InitDemo {private static String lsFile = "taget/ls.txt";//下载public void downLoaing(String STRURL) {try {ExecutorService service = Executors.newCachedThreadPool();URL url = new URL(STRURL);HttpURLConnection connection = (HttpURLConnection) url.openConnection();long fileLength = connection.getContentLength();Thread threadA = null;Thread threadB = null;Thread threadC = null;Thread threadD = null;long FileDuan = fileLength/4;threadA = new Thread(new MyDownLoadingThread(STRURL, new long[] {0,FileDuan}), "A");threadB = new Thread(new MyDownLoadingThread(STRURL, new long[] {FileDuan+1,FileDuan*2}), "B");threadC = new Thread(new MyDownLoadingThread(STRURL, new long[] {FileDuan*2+1,FileDuan*3}), "C");threadD = new Thread(new MyDownLoadingThread(STRURL, new long[] {FileDuan*3+1,fileLength}), "D");service.submit(threadA);service.submit(threadB);service.submit(threadC);service.submit(threadD);service.shutdown();while(true) {if(service.isTerminated()) {System.out.println("下载完成!");//下载完成删除产生的临时文件new File(lsFile).delete();break;}else {Thread.sleep(200);}}
// threadA.start();
// threadB.start();
// threadC.start();
// threadD.start(); } catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} }}
3.测试类:
package 多线程下载器;import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Scanner;public class TextDemo {//private static String STRURL = "http://pic.ibaotu.com/00/63/22/31Q888piC7wM.mp4";public static void main(String[] args) {Scanner in = new Scanner(System.in);InitDemo initDemo = new InitDemo();System.out.println("---HTTP下载器,输入END结束---");while(true) {System.out.print("请输入你要下载的HTTP地址: ");String str = in.next();if(str.equals("END")) {System.exit(0);}initDemo.downLoaing(str);}}
}
运行效果:
束语:
由于没有学习过图形界面所以就把核心代码写上了然后做的比较粗糙233333,当然这不是最优代码,因为每次写入临时文件比较耗时资源
如果更好的思路,留言一下吧=-=,毕竟新手上路
多线程实现HTTP下载器(断点续传)_使用IO和线程知识相关推荐
- 利用多线程实现的下载器,完爆迅雷!
原文:利用多线程实现的下载器,完爆迅雷! 源代码下载地址:http://www.zuidaima.com/share/1550463611374592.htm 方便,快捷~~~程序猿必备利器 界面是用 ...
- python编写下载器可暂停_python多进程断点续传分片下载器
python多进程断点续传分片下载器 标签:python 下载器 多进程 因为爬虫要用到下载器,但是直接用urllib下载很慢,所以找了很久终于找到一个让我欣喜的下载器.他能够断点续传分片下载,极大提 ...
- 电脑下载软件用什么软件好?安卓手机下载软件用哪个软件好?IDM下载器说:在做的都是弟弟
大年初五,迎财神,先祝大家新的一年财源滚滚,接下来为大家分享超级经典的IDM下载器,电脑端毫无争议的下载工具,安卓平台idm也是力压群雄,下面就为大家详细分享下: 1:1DM+下载 ...
- python爬虫图片实例-【图文详解】python爬虫实战——5分钟做个图片自动下载器...
我想要(下)的,我现在就要 python爬虫实战--图片自动下载器 之前介绍了那么多基本知识[Python爬虫]入门知识(没看的赶紧去看)大家也估计手痒了.想要实际做个小东西来看看,毕竟: talk ...
- 【图文详解】python爬虫实战——5分钟做个图片自动下载器
python爬虫实战--图片自动下载器 之前介绍了那么多基本知识[Python爬虫]入门知识,大家也估计手痒了.想要实际做个小东西来看看,毕竟: talk is cheap show me the c ...
- 撸了个多线程断点续传下载器,我从中学习到了这些知识(附开源地址)
2020年6月20日 上海张江 感谢看客老爷点进来了,周末闲来无事,想起同事强哥的那句话:"你有没有玩过断点续传?" 当时转念一想,断点续传下载用的确实不少,具体细节嘛,真的没有去 ...
- 安卓day29网络编程 HttpClient AsyncHttpClient 断点续传多线程下载器 HttpUtils
一.排坑 HttpClient.Header飘红 Android 6.0 已经移除了httpClient module下的build.gradle中加入: android{useLibrary 'or ...
- Python图片下载器(单线程PK多线程)_一蓑烟雨任平生
文章目录 前言 一.单线程下载图片 二.多线程爬取图片 总结 前言 爬取图片很简单,但是单线程跟多线程的对比就不一样了,可以看到下载速度 一.单线程下载图片 # =================== ...
- 使用C#制作Windows窗体应用,实现一个微端下载器功能(多线程/断点续传/微端/下载器)
文章目录 一.前言 二.最终运行效果 三.Demo工程下载 四.工程类型 五.工程结构 六.多线程下载核心代码 一.前言 在PC端的QQ游戏大厅下载游戏的时候,我们会发现很多游戏都自己做了微端下载器, ...
最新文章
- Packet Tracer 5.0配置cisco路由器详细说明
- madvr设置_用Kodi+MadVR播放4k HDR原盘电影方法
- dx:ASPxGridView 批量删除
- 【MDCC技术大咖秀】Android内存优化之OOM
- Oracle配置OneMap中的sql数据库问题及解决方案
- linux kill pid文件,从一次事故谈谈 pid 文件的作用
- 前端编程之jQuery
- 突破领域边界,探索文创文保新趋势
- vue_axios详解
- Android: 创建一个AlertDialog对话框,必须按确定或取消按钮才能关闭对话框,禁止按[返回键]或[搜索键]关闭
- js(Dom+Bom)第八天
- HashMap深度解析:一文让你彻底了解HashMap
- Kubernetes-2018干货盘点
- unity 企鹅砸小猪 笔记1
- Ajax技术复习---狂神笔记
- 计算机网络体系结构图解
- r语言计算行列式的值
- 使用 Notepad 或 TextEdit 来编写 HTML
- nginx 499状态码
- 994. 腐烂的橘子 (广度探索)
热门文章
- 3.17学堂在线python学习笔记
- python做游戏服务器_浅谈如何做一个游戏服务器
- 人群里,我更中意温和寡言之人
- docker网络模式与none模式配置网络
- php 求最大连续子序列,[HDOJ 1003]动态规划法求和最大的连续子序列
- url传参时中文乱码转码的两种方式
- Hp 通过MP卡启动、关闭电源 Hp9000小型机的方式
- 初识 love2d. Hello World lua 调试 iOS 环境运行
- 计算机教育格言,苏霍姆林斯基教育名言大全
- Access denied for user 'mysql用户名'@'主机或IP' (using password: YES)'