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之多线程断点下载的实现的更多相关文章

  1. Java实现多线程断点下载(下载过程中可以暂停)

    线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...

  2. Android(java)学习笔记216:多线程断点下载的原理(Android实现)

    之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1.新建一个Android工程: (1)其中我们先实现布局 ...

  3. Android(java)学习笔记159:多线程断点下载的原理(Android实现)

    之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1. 新建一个Android工程: (1)其中我们先实现布 ...

  4. java多线程断点下载原理(代码实例演示)

    原文:http://www.open-open.com/lib/view/open1423214229232.html 其实多线程断点下载原理,很简单的,那么我们就来先了解下,如何实现多线程的断点下载 ...

  5. andoid 多线程断点下载

    本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多 ...

  6. 我的Android进阶之旅------>Android基于HTTP协议的多线程断点下载器的实现

    一.首先写这篇文章之前,要了解实现该Android多线程断点下载器的几个知识点 1.多线程下载的原理,如下图所示 注意:由于Android移动设备和PC机的处理器还是不能相比,所以开辟的子线程建议不要 ...

  7. iOS开发网络篇—大文件的多线程断点下载

    http://www.cnblogs.com/wendingding/p/3947550.html iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时 ...

  8. iOS开发网络请求——大文件的多线程断点下载

    iOS开发中网络请求技术已经是移动app必备技术,而网络中文件传输就是其中重点了.网络文件传输对移动客户端而言主要分为文件的上传和下载.作为开发者从技术角度会将文件分为小文件和大文件.小文件因为文件大 ...

  9. iOS开发网络篇—大文件的多线程断点下载(转)

    http://www.cnblogs.com/wendingding/p/3947550.html   iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了 ...

随机推荐

  1. spring 构造注入 异常 Ambiguous constructor argument types - did you specify the correct bean references as constructor arguments

    你可能在做项目的时候,需要在项目启动时初始化一个自定义的类,这个类中包含着一个有参的构造方法,这个构造方法中需要传入一些参数. spring提供的这个功能叫“构造注入”, applicationCon ...

  2. ie8 background css没有显示?——都是空格惹的祸

    ie8 background css没有显示?——都是空格惹的祸

  3. js 代码记录

    window.screen.availWidth 返回当前屏幕宽度(空白空间) window.screen.availHeight 返回当前屏幕高度(空白空间) window.screen.width ...

  4. C#实现对邮件的发送

    首先是邮件帮助类 using System; using System.Collections.Generic; using System.Text; using System.Net.Mail; u ...

  5. jquery升级换代

    其实从去年开始1.9以上新版的jquery已不再支持toggle方法和live方法. live用on方法替代. 话说这个方法确实挺方便的,那么怎么交替点击呢,html的checked属性我觉得不是很好 ...

  6. STM32F10x 学习笔记5(USART实现串口通讯 1)

    STM32F10x 系列单片机中都包含了USART 模块,所谓USART,就是通用同步异步收发器.通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间 ...

  7. Qt如何去掉按钮等控件的虚线框(焦点框)(三种办法)

    方法1:可以通过代码ui->pushButton->setFocusPolicy(Qt::NoFocus)或在Qt Creator的属性列表中设置. 方法2:如果在嵌入式设备中需要通过按键 ...

  8. 我的VSTO之路(三):Word基本知识

    原文:我的VSTO之路(三):Word基本知识 在前一篇文章中,我初步介绍了如何如何开发一个VSTO程序,在本文中,我将进一步深入介绍Word的插件开发.Word是一个大家在日常工作中一直接触的文档工 ...

  9. 静态与动态IP设置

    静态IP设置 netsh interface ipv4 set address name="本地连接" source=static addr=192.168.0.212 (这个地方 ...

  10. shell command使用技巧

    1窗口可以merge 2.可以通过 control+t打开窗口