多线程断点续传(代码,附有详细注解)
来源:互联网 发布:linux递归创建目录 编辑:程序博客网 时间:2024/05/21 07:06
--------------------------------Activity------------------------------------------------------
------------------------------------------------------------------------------------------------
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
String path = "http://169.254.88.88:8080/LiebaoFreeWiFi5.1.exe";
int threadCount = 3;
int finishedThread = 0;
//所有线程下载总进度
int downloadProgress = 0;
private ProgressBar pb;
private TextView tv;
Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
tv.setText((long)pb.getProgress() * 100 / pb.getMax() + "%");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pb = (ProgressBar) findViewById(R.id.pb);
tv = (TextView) findViewById(R.id.tv);
}
public void click(View v){
Thread t = new Thread(){
@Override
public void run() {
//发送http请求,拿到目标文件长度
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(8000);
conn.setReadTimeout(8000);
if(conn.getResponseCode() == 200){
//获取长度
int length = conn.getContentLength();
//创建临时文件
File file = new File(Environment.getExternalStorageDirectory(), getNameFromPath(path));
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
//设置临时文件大小与目标文件一致
raf.setLength(length);
raf.close();
//设置进度条的最大值
pb.setMax(length);
//计算每个线程下载区间
int size = length / threadCount;
for (int id = 0; id < threadCount; id++) {
//计算每个线程下载的开始位置和结束位置
int startIndex = id * size;
int endIndex = (id + 1) * size - 1;
if(id == threadCount - 1){
endIndex = length - 1;
}
System.out.println("线程" + id + "下载的区间:" + startIndex + " ~ " + endIndex);
new DownLoadThread(id, startIndex, endIndex).start();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t.start();
}
public String getNameFromPath(String path){
int index = path.lastIndexOf("/");
return path.substring(index + 1);
}
class DownLoadThread extends Thread{
int threadId;
int startIndex;
int endIndex;
public DownLoadThread(int threadId, int startIndex, int endIndex) {
super();
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
@Override
public void run() {
try {
File fileProgress = new File(Environment.getExternalStorageDirectory(), threadId + ".txt");
int lastProgress = 0;
if(fileProgress.exists()){
//读取进度临时文件中的内容
FileInputStream fis = new FileInputStream(fileProgress);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
//得到上一次下载进度
lastProgress = Integer.parseInt(br.readLine());
//改变下载的开始位置,上一次下过的,这次就不请求了
startIndex += lastProgress;
fis.close();
//把上一次下载进度加到进度条进度中
downloadProgress += lastProgress;
//发送消息,让文本进度条改变
handler.sendEmptyMessage(1);
}
//发送http请求,请求要下载的数据
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(8000);
conn.setReadTimeout(8000);
//设置请求数据的区间
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
//请求部分数据,成功的响应码是206
if(conn.getResponseCode() == 206){
InputStream is = conn.getInputStream();
byte[] b = new byte[1024];
int len = 0;
//当前线程下载的总进度
int total = lastProgress;
File file = new File(Environment.getExternalStorageDirectory(), getNameFromPath(path));
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
//设置写入的开始位置
raf.seek(startIndex);
while((len = is.read(b)) != -1){
raf.write(b, 0, len);
total += len;
System.out.println("线程" + threadId + "下载了:" + total);
//创建一个进度临时文件,保存下载进度
RandomAccessFile rafProgress = new RandomAccessFile(fileProgress, "rwd");
//每次下载1024个字节,就,就马上把1024写入进度临时文件
rafProgress.write((total + "").getBytes());
rafProgress.close();
//每次下载len个长度的字节,马上把len加到下载进度中,让进度条能反应这len个长度的下载进度
downloadProgress += len;
pb.setProgress(downloadProgress);
//发送消息,让文本进度条改变
handler.sendEmptyMessage(1);
}
raf.close();
System.out.println("线程" + threadId + "下载完毕------------------");
//3条线程全部下载完毕,才去删除进度临时文件
finishedThread++;
synchronized (path) {
if(finishedThread == threadCount){
for (int i = 0; i < threadCount; i++) {
File f = new File(Environment.getExternalStorageDirectory(), i + ".txt");
f.delete();
}
finishedThread = 0;
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
----------------------------------------Layout---------------------------------------------------
------------------------------------------------------------------------------------------------
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:orientation="vertical"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下载"
android:onClick="click"
/>
<ProgressBar
style="@android:style/Widget.ProgressBar.Horizontal"
android:id="@+id/pb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0%"
android:layout_gravity="right"
/>
</LinearLayout>
下载地址:
http://download.csdn.net/detail/github_36186415/9637992
- 多线程断点续传(代码,附有详细注解)
- 贪吃蛇游戏~~~c++代码全文。。。附有详细注释。。。。。。
- Java多线程断点续传代码详解
- 多线程断点续传(一)
- 多线程断点续传(二)
- 五子棋代码详细注解
- caffe代码详细注解
- Java代码实现多线程下载和断点续传
- Java代码实现多线程下载和断点续传
- ID3算法(附有java和c++代码实现)
- Mapreduce读取和写入Hbase(从A表读取数据,统计结果放入B表,非常详细,附有代码说明以及流程)
- 多线程详细解说,代码
- 多线程断点续传
- 多线程断点续传
- 多线程断点续传
- 多线程断点续传
- 多线程断点续传
- 多线程断点续传
- windows10安装python出现错误2502/2503解决方法
- Poj 2456 Aggressive cows【贪心+二分】
- 子类无参构造调用父类有参构造方法
- swift学习笔记--swift3.0 if-let、guard语句中的where的替换
- 【BZOJ 1833】【数位DP】 ZJOI2010 count【求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次】
- 多线程断点续传(代码,附有详细注解)
- mysql 5.7插入中文乱码,mysql 5.7 修改my.ini文件无效解决方法
- 算法2.5:链式A+B
- C++ 作用域运算符(::)
- C++模板-实现栈(进制转换)
- Android 播放视频 VideoView 《第一行代码》学习笔记
- php缓存-内存式-mamcache-封装
- 【2016-沈阳赛区网络赛-I】区间DP(QSC and Master,hdu 5900)
- UVa 12169 Disgruntled Judge