Java之多线程断点下载的实现
RandomAccessFile类:
此类的实例支持对随机訪问文件的读取和写入。随机訪问文件的行为相似存储在文件系统中的一个大型 byte 数组。
存在指向该隐含数组。光标或索引,称为文件指针。输入操作从文件指针開始读取字节。并随着对字节的读取而前移此文件指针。
假设随机訪问文件以读取/写入模式创建,则输出操作也可用。输出操作从文件指针開始写入字节。并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针能够通过 getFilePointer 方法读取。并通过 seek 方法设置。
以下有RandomAccessFile实现安卓下的断点下载的demo。
server端能够用tomcat模拟。将被下载的測试文件放入webApp/ROOT文件夹下就可以。
先给出java借助HttpURLConnection类实现的多线程下载代码:
public class MultiThread {
private static int threadCount = 3;
private static long blockSize;
private static int runningThreadCount;
public static void main(String[] args) throws Exception {
String path = "http://10.0.67.172/test.exe";
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);//超时时间
int code = conn.getResponseCode();
System.out.println(code);
if(code / 100 == 2){
int size = conn.getContentLength();//获取资源文件的长度
System.out.println("请求资源大小:" + size);
blockSize = size / threadCount;//将资源文件分为多少块。没一块的大小
runningThreadCount = threadCount;
long startIndex = 0;
long endIndex = 0;
//开启若干个子线程去实现多线程的下载
for(int i = 0; i < threadCount; i++){
startIndex = i * blockSize;
endIndex = (i + 1) * blockSize - 1;
if(i == threadCount-1){
endIndex = size - 1;
}
System.out.println("开启线程:" + i + ";" + "開始位置:" + startIndex + ":" + "结束位置:" + endIndex);
new DownThread(path, startIndex, endIndex, i).start();
}
}
}
private static class DownThread extends Thread{
private String path;
private long startIndex;
private long endIndex;
private int threadId;
public DownThread(String path, long startIndex, long endIndex, int threadId) {
super();
this.path = path;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);//设置server上的文件的读取位置
int code = conn.getResponseCode();
if(code / 100 == 2){
InputStream is = conn.getInputStream();
File file = new File("temp.exe");
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.seek(startIndex);
System.out.println("第" + threadId + "个文件的開始位置:" + String.valueOf(startIndex));
int len = 0;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) != -1){
raf.write(buffer, 0, len);//写文件
}
raf.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
断点下载的原理就是将上次文件下载的位置保存为暂时文件,当全然完成下载时再删除。
public class MultiThread {
private static int threadCount = 3;
private static long blockSize;
private static int runningThreadCount;
public static void main(String[] args) throws Exception {
String path = "http://10.0.67.172/test.rar";
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);//超时时间
int code = conn.getResponseCode();
System.out.println(code);
if(code / 100 == 2){
int size = conn.getContentLength();//获取资源文件的长度
System.out.println("请求资源大小:" + size);
blockSize = size / threadCount;//将资源文件分为多少块,没一块的大小
runningThreadCount = threadCount;
long startIndex = 0;
long endIndex = 0;
for(int i = 0; i < threadCount; i++){
startIndex = i * blockSize;
endIndex = (i + 1) * blockSize - 1;
if(i == threadCount-1){
endIndex = size - 1;
}
System.out.println("开启线程:" + i + ";" + "開始位置:" + startIndex + ":" + "结束位置:" + endIndex);
new DownThread(path, startIndex, endIndex, i).start();
}
}
}
private static class DownThread extends Thread{
private String path;
private long startIndex;
private long endIndex;
private int threadId;
public DownThread(String path, long startIndex, long endIndex, int threadId) {
super();
this.path = path;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}
@Override
public void run() {
int total = 0;
try {
File positionFile = new File(threadId + ".txt");
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
//接着上次的文件继续下载
if(positionFile.exists() && positionFile.length() > 0){
FileInputStream fis = new FileInputStream(positionFile);
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
//获取当前线程上次下载的总大小是多少
String lasttotalstr = reader.readLine();
int lastTotal = Integer.valueOf(lasttotalstr);
System.out.println("上次线程下载的总大小:" + lastTotal);
startIndex += lastTotal;
total += lastTotal;
fis.close();
}
conn.setReadTimeout(5000);
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);//设置server上的文件的读取位置
int code = conn.getResponseCode();
if(code / 100 == 2){
InputStream is = conn.getInputStream();
File file = new File("temp.rar");
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.seek(startIndex);
System.out.println("第" + threadId + "个文件的開始位置:" + String.valueOf(startIndex));
int len = 0;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) != -1){
RandomAccessFile rf = new RandomAccessFile(positionFile, "rwd");
raf.write(buffer, 0, len);//写文件
total += len;
rf.write(String.valueOf(total).getBytes());
rf.close();
}
is.close();
raf.close();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
synchronized (DownThread.class) {
System.out.println("线程" + threadId + "完成下载了");
runningThreadCount--;
if (runningThreadCount < 1) {
System.out.println("全部的线程都工作完成了。删除暂时记录的文件");
for (int i = 0; i < threadCount; i++) {
File f = new File(i + ".txt");
System.out.println(f.delete());
}
}
}
}
}
}
}
执行结果截图:
Java之多线程断点下载的实现的更多相关文章
- Java实现多线程断点下载(下载过程中可以暂停)
线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...
- Android(java)学习笔记216:多线程断点下载的原理(Android实现)
之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1.新建一个Android工程: (1)其中我们先实现布局 ...
- Android(java)学习笔记159:多线程断点下载的原理(Android实现)
之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1. 新建一个Android工程: (1)其中我们先实现布 ...
- java多线程断点下载原理(代码实例演示)
原文:http://www.open-open.com/lib/view/open1423214229232.html 其实多线程断点下载原理,很简单的,那么我们就来先了解下,如何实现多线程的断点下载 ...
- andoid 多线程断点下载
本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多 ...
- 我的Android进阶之旅------>Android基于HTTP协议的多线程断点下载器的实现
一.首先写这篇文章之前,要了解实现该Android多线程断点下载器的几个知识点 1.多线程下载的原理,如下图所示 注意:由于Android移动设备和PC机的处理器还是不能相比,所以开辟的子线程建议不要 ...
- iOS开发网络篇—大文件的多线程断点下载
http://www.cnblogs.com/wendingding/p/3947550.html iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时 ...
- iOS开发网络请求——大文件的多线程断点下载
iOS开发中网络请求技术已经是移动app必备技术,而网络中文件传输就是其中重点了.网络文件传输对移动客户端而言主要分为文件的上传和下载.作为开发者从技术角度会将文件分为小文件和大文件.小文件因为文件大 ...
- iOS开发网络篇—大文件的多线程断点下载(转)
http://www.cnblogs.com/wendingding/p/3947550.html iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了 ...
随机推荐
- 复制JAVABEAN中的属性到另外一个JAVABEAN中
下午写了一个属性复制方法,记录如下: class POUtil{ /** * * Function : 将一个source中的属性到复制到dest * @author : Liaokailin * C ...
- window对象细节(转载)
Window对象是客户端javascript最高层对象之一,只要打开浏览器窗口,不管该窗口中是否有打开的网页,当遇到BODY.FRAMESET或FRAME元素时,都会自动建立window对象的实例.另 ...
- 利用正则表达式,给Json字段加引号
{ scheme: [ { query: [ [{ id: 'stdNumber', title: "标准号", compareType: 2 }], [{ id: 'CnName ...
- PHP框架_Smarty
目录 1.环境搭建 2.基本配置 3.Smarty变量调节器 4.Smarty条件判断 5.Smarty的循环 6.Smarty模板的引用 7.Smarty类与对象的赋值与引用 8.smarty函数插 ...
- 我的css reset
@charset "utf-8"; /*reset*/ body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,f ...
- 知识库系统/知识管理系统 WCP
知识库系统/知识管理系统 WCP 本项目的应用场景是管理技术团队的相关知识(API.代码片段.知识定义.技术经验...) 但是其应用并不局限于这些应用,当然你最好下载一个安装版先试一试.其实这就是一个 ...
- Java中权限修饰符public、private、protected和default的区别
1.public 可以修饰类.成员变量和成员函数,没有任何限制,同一个包中,或者不同包中的类都可以自由访问 2.private 可以修饰成员变量和成员函数,只能在本类中使用 3.default (不写 ...
- JavaScript 项目构建工具 Grunt 实践:安装和创建项目框架
Grunt 是一个基于任务的 JavaScript 项目命令行构建工具,运行于 Node.js 平台.Grunt 能够从模板快速创建项目,合并.压缩和校验 CSS & JS 文件,运行单元测 ...
- C语言中如何使用宏
C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 宏使用中的常见的基础问题 #符号和##符号的使用 ...符号的 ...
- 如何给Qlabel添加clicked属性(覆盖mousePressEvent,处理QMouseEvent消息,反正是软绘制,想怎么样就怎么样)
clickedLabel.h #ifndef CLICKLABEL_H #define CLICKLABEL_H #include <QLabel> #include <QMouse ...