文件的下载和断电续传
2016-02-07 16:26
573 查看
[1]文件的分块
[2]断点的保存
使用RandomAccessFile 类,不停留在缓冲区,而是直接写进外存
[3]删除断点文件是使用互斥访问
[2]断点的保存
使用RandomAccessFile 类,不停留在缓冲区,而是直接写进外存
RandomAccessFile raff=new RandomAccessFile(getFileName(path)+threadId+".txt", "rwd");
[3]删除断点文件是使用互斥访问
//互斥访问 synchronized (DownLoadThread.class) { runingThread--; if (runingThread==0) { for (int i = 0; i < threadCount; i++) { File deleteFile=new File(getFileName(path)+i+".txt"); deleteFile.delete(); } }
package jacky.mutildownload; import android.os.Bundle; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ProgressBar; import java.io.BufferedReader; import java.io.File; import java.io.FileInput 4000 Stream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private EditText ed_downloadurl; private EditText ed_threadcount; private LinearLayout ll_pb; private String path; private int threadCount; private int runingThread = 0; private List<ProgressBar> pbLists; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //找到我们的控件 ed_downloadurl = (EditText) findViewById(R.id.ed_downloadurl); ed_threadcount = (EditText) findViewById(R.id.ed_threadcount); ll_pb = (LinearLayout) findViewById(R.id.ll_pb); //添加进度条引用 pbLists = new ArrayList<ProgressBar>(); } //下载 public void click(View v) { //获取url 和 线程数量 path = ed_downloadurl.getText().toString().trim(); threadCount = Integer.parseInt(ed_threadcount.getText().toString().trim()); //先移除所有进度条,再进行进度条增加 ll_pb.removeAllViews(); pbLists.clear(); for (int i=0;i<threadCount;i++){ //打气筒 ProgressBar pbView=(ProgressBar)View.inflate(getApplicationContext(),R.layout.item,null); //把pbView添加到集合中 pbLists.add(pbView); //动态添加一个进度条 ll_pb.addView(pbView); } //进行下载的逻辑 new Thread(){ @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(5000); conn.setRequestMethod("GET"); int code = conn.getResponseCode(); if (code == 200) { //把线程数量赋值给正在运行的线程 runingThread= threadCount; int length = conn.getContentLength(); // 计算出每个线程下载的大小 int blockSize = length / threadCount; // 计算每个线程下载的开始和结束位置 for (int i = 0; i < threadCount; i++) { int startIndex = i * blockSize; int endIndex = (i + 1) * blockSize - 1; // 如果为最后一个线程,则多下载些,下载到结尾 if (i == threadCount - 1) { endIndex = length - 1; } System.out.println("线程id:"+i+"理论下载位置"+startIndex+"---"+endIndex); // 创建线程 DownLoadThread downLoadThread = new DownLoadThread( startIndex, endIndex, i); downLoadThread.start(); } } } catch (Exception e) { e.printStackTrace(); } } }.start(); } private class DownLoadThread extends Thread { private int startIndex; private int endIndex; private int threadId; private int pbMaxSize;//进度条的最大值 private int pblastPostion=0;//上次下载重点的位置 public DownLoadThread(int startIndex, int endIndex, int threadId) { this.startIndex = startIndex; this.endIndex = endIndex; this.threadId = threadId; } @Override public void run() { try { pbMaxSize=endIndex-startIndex; URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.setReadTimeout(8000); conn.setRequestMethod("GET"); //读取断点。 //TODO File file=new File(getFileName(path)+threadId+".txt"); if (file.exists()&&file.length()>0) { FileInputStream fis = new FileInputStream(file); BufferedReader bufr=new BufferedReader(new InputStreamReader(fis)); String lastpostionn=bufr.readLine(); int lastpostion = Integer.parseInt(lastpostionn); //创建进度条的开始位置 pblastPostion=lastpostion-startIndex; //改变一下开始位置 startIndex=lastpostion+1; System.out.println("线程id:"+threadId+"真是下载位置"+startIndex+"---"+endIndex); //关闭流 fis.close(); } // 设置一个请求头 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); int code = conn.getResponseCode(); // 200请求全部资源成功 206请求部分资源成功 if (code == 206) { // 创建随机读写对象 RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw"); // 设置开始写的位置 raf.seek(startIndex); InputStream in = conn.getInputStream(); // 写数据到文件中 int len = -1; //设置缓冲区为5M byte[] buffer = new byte[1024*1024*5]; int total = 0;//代表当前线程下载的大小 while ((len = in.read(buffer)) != -1) { raf.write(buffer, 0, len); total+=len; //将实现断点续传的位置存起来,存到一个.txt中 int currentThreadPosition=startIndex+total; RandomAccessFile raff=new RandomAccessFile(getFileName(path)+threadId+".txt", "rwd"); raff.write(String.valueOf(currentThreadPosition).getBytes()); raff.close(); //设置进度条的最大长度 pbLists.get(threadId).setMax(pbMaxSize); //设置进度条的当前位置 pbLists.get(threadId).setProgress(pblastPostion+total); } raf.close(); System.out.println("线程id:" + threadId + "下载完成"); //互斥访问 synchronized (DownLoadThread.class) { runingThread--; if (runingThread==0) { for (int i = 0; i < threadCount; i++) { File deleteFile=new File(getFileName(path)+i+".txt"); deleteFile.delete(); } } } } } catch (Exception e) { e.printStackTrace(); } } }; public String getFileName(String path) { int start=path.lastIndexOf("/")+1; //写到SD卡 String pathName= Environment.getExternalStorageDirectory().getPath()+"/"+path.substring(start); return pathName; } }
相关文章推荐
- Android Native 绘图方法
- C#中struct和class的区别详解
- C#文件断点续传实现方法
- VBS ArrayList Class vbs中的数组类
- 大家看了就明白了css样式中类class与标识id选择符的区别小结
- PHP简单实现断点续传下载的方法
- 深入了解PHP类Class的概念
- jquery 表单验证之通过 class验证表单不为空
- setAttribute 与 class冲突解决
- JavaScript中的类(Class)详细介绍
- javascript面向对象包装类Class封装类库剖析
- 详解js中class的多种函数封装方法
- jQuery使用hide方法隐藏指定元素class样式用法实例
- jQuery给多个不同元素添加class样式的方法
- jQuery点击改变class并toggle及toggleClass()方法定义用法
- jquery采用oop模式class类的使用示例
- JavaScript更改class和id的方法
- 一篇入门的php Class 文章
- 深入C++中struct与class的区别分析
- js中设置元素class的三种方法小结