Java之多线程断点下载的实现

RandomAccessFile类: 此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组,光标或索引,,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。

下面有RandomAccessFile实现安卓下的断点下载的demo。 服务器端可以用tomcat模拟,将被下载的测试文件放入webApp/ROOT目录下即可。 先给出java借助HttpURLConnection类实现的多线程下载代码:

{threadCount = 3;blockSize;runningThreadCount;(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 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;}() {try {URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod(“GET”);conn.setReadTimeout(5000);conn.setRequestProperty(“Range”, “bytes=” + startIndex + “-” + endIndex);//设置服务器上的文件的读取位置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();}}}}

断点下载的原理就是将上次文件下载的位置保存为临时文件,当完全下载完毕时再删除。

{threadCount = 3;blockSize;runningThreadCount;(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 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;}() {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);//设置服务器上的文件的读取位置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之多线程断点下载的实现

相关文章:

你感兴趣的文章:

标签云: