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开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了 ...
随机推荐
- 绑定下拉框时避免触发SelectedIndexChanged事件
在从数据库读取数据集绑定到下拉框时会立即触发其SelectedIndexChanged事件造成异常,可对其SelectedIndexChanged事件采取先解除后附加的方法解决. cmbXl_gt.V ...
- C# winform 右下角弹窗
[DllImport("user32")] private static extern bool AnimateWindow(IntPtr hwnd, int dwTime, in ...
- TabControl控件中TabPage的显示和隐藏
TabPage里面含有方法Hide和Show,但没有任何作用,实际隐藏和显示需要使用如下2个方法 方法一:此方法比较简单 TabPageServo.Parent = Nothing //隐藏 Ta ...
- 使用Raphael 画图(二) 扩展的图形 (javascript)
看这文章前,建议先看第一编文章<使用Raphael 画图(一) 基本图形 (javascript)>. 在Raphael基础上扩展的图形: 要运行该例子要引入附件的2个js包.(g.rap ...
- IOS开发备忘
1. ios 真机调试时出现CopyPngFile error解决方法 说是读取的时候没有找到这张图片,检查了一下图片路径,没有问题,于是google之,找到两种解决方法 : 方法一:在build s ...
- Day11 线程、进程、协程
创建线程第一种:import threadingdef f1(arg): print(arg) t = threading.Thread(target=f1, args=(123,))#t.start ...
- Python中几种数据结构的整理,列表、字典、元组、集合
列表:shoplist = ['apple', 'mango', 'carrot', 'banana']字典:di = {'a':123,'b':'something'}集合:jihe = {'app ...
- 解决Silverlight5_tools无法安装问题(试验已成功)
当前位置: 银光首页 > Silverlight > Silverlight学习教程 > 命令:regedit 打开节点:HKEY_LOCAL_MACHINE\SOFTWARE\Mi ...
- 强制不使用“兼容性视图”的HTML代码(转)
在IE8浏览器以后版本,都有一个“兼容性视图”,让不少新技术无法使用.那么如何禁止浏览器自动选择“兼容性视图”,强制IE以最高级别的可用模式显示内容呢?下面就介绍一段HTML代码. X-UA-Comp ...
- Google测试精华文章(1) - 测试行为,而非实现
Your trusty Calculator class is one of your most popular open source projects, with many happy users ...