- 浏览: 150643 次
- 性别:
- 来自: 深圳
最新评论
package mydown; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 多线程断点续传 * * @author kinkding * @history 2009-7-25 */ public class TestMyDown { int threads; String rootPath = "F:/mydown"; String fileName = ""; URL downUrl; CountDownLatch latch; public TestMyDown(String strUrl, int threads) throws MalformedURLException { downUrl = new URL(strUrl); this.threads = threads; fileName = strUrl.substring(strUrl.lastIndexOf('/') + 1); latch = new CountDownLatch(threads); } public int run() throws IOException { // 创建根路径 File rootFile = new File(rootPath); if (!rootFile.exists()) { rootFile.mkdirs(); } HttpURLConnection urlConn = (HttpURLConnection) downUrl.openConnection(); this.setHeader(urlConn); long totalLength = urlConn.getContentLength(); long threadLength = totalLength / threads; // 设置断点 long startPos[] = this.setBreakPoint(totalLength); // 开始进行多线程下载 DownThread downThreads[] = new DownThread[threads]; ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < threads; i++) { startPos[i] += threadLength * i; long endPos = i == threads - 1 ? totalLength : (threadLength * (i + 1) - 1); // 开启子线程并执行 DownThread child = new DownThread(startPos[i], endPos, i); downThreads[i] = child; exec.execute(child); } try { // 等待所有线程下载完成 latch.await(); exec.shutdown(); // 开始合并文件 this.mergeFile(downThreads); } catch (InterruptedException e) { e.printStackTrace(); } return 1; } private long[] setBreakPoint(long totalLength) throws IOException { long startPos[] = new long[threads]; File file = new File(this.rootPath + '/' + this.fileName); if (file.exists() && file.length() < totalLength) { File root = new File(this.rootPath); for (File f : root.listFiles()) { String name = f.getName(); long length = f.length(); if (name != null && length > 0 && name.startsWith(this.fileName + '_')) { startPos[Integer.parseInt(name.substring(name.lastIndexOf('_') + 1))] = length; } } } else { file.createNewFile(); } return startPos; } private void mergeFile(DownThread downThreads[]) throws IOException { BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(this.rootPath + "/" + this.fileName)); for (int i = 0; i < threads; i++) { BufferedInputStream input = new BufferedInputStream(new FileInputStream( downThreads[i].file)); int len = 0; long count = 0; byte[] b = new byte[1024]; while ((len = input.read(b)) != -1) { count += len; output.write(b, 0, len); if ((count % 4096) == 0) { output.flush(); } } input.close(); downThreads[i].file.delete(); } output.flush(); output.close(); System.out.println(fileName + " ok!"); } private void setHeader(HttpURLConnection urlConn) { // 模拟浏览器的访问 urlConn .setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1"); urlConn.setRequestProperty("Accept-Language", "zh-cn,zh;q=0.5"); urlConn.setRequestProperty("Accept-Charset", "GB2312,utf-8;q=0.7,*;q=0.7"); urlConn.setRequestProperty("Keep-Alive", "300"); urlConn.setRequestProperty("Connection", "keep-alive"); urlConn.setRequestProperty("Cache-Control", "max-age=0"); urlConn.setRequestProperty("Referer", downUrl.getPath()); } class DownThread extends Thread { private File file; private int id; private long startPos; private long endPos; public DownThread(long startPos, long endPos, int id) { super(); this.startPos = startPos; this.endPos = endPos; this.id = id; file = new File(rootPath + "/" + fileName + "_" + id); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } } public void run() { System.out.println("thread " + id + " start..."); HttpURLConnection con = null; InputStream inputStream = null; BufferedOutputStream outputStream = null; long count = 0; try { outputStream = new BufferedOutputStream(new FileOutputStream(file.getPath(), true)); } catch (FileNotFoundException e) { e.printStackTrace(); } while (true) { try { con = (HttpURLConnection) downUrl.openConnection(); setHeader(con); con.setAllowUserInteraction(true); con.setConnectTimeout(1000); con.setReadTimeout(1000); if (startPos < endPos) { // 设置下载数据的起止区间 System.out.println("thread" + id + " bytes=" + startPos + "-" + endPos); con.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); int code = con.getResponseCode(); // 服务器是否响应成功 if (code != HttpURLConnection.HTTP_OK && code != HttpURLConnection.HTTP_PARTIAL) { outputStream.close(); con.disconnect(); latch.countDown(); break; } inputStream = con.getInputStream(); int len = 0; byte[] b = new byte[1024]; while ((len = inputStream.read(b)) != -1) { outputStream.write(b, 0, len); count += len; startPos += len; if (count % 4096 == 0) { outputStream.flush(); } } outputStream.flush(); outputStream.close(); inputStream.close(); con.disconnect(); } System.out.println("thread " + id + " end."); latch.countDown(); break; } catch (IOException e) { try { outputStream.flush(); inputStream.close(); con.disconnect(); // 2秒后重连 TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e1) { e1.printStackTrace(); } catch (IOException e2) { e2.printStackTrace(); } continue; } } // 循环终止 if (outputStream != null) { try { outputStream.close(); con.disconnect(); } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String[] args) { String url = "http://i1.sinaimg.cn/dy/hdphoto/2009/0425/U1565P1T557D132F12892DT20090425105719.jpg"; try { TestMyDown mydown = new TestMyDown(url, 4); mydown.run(); } catch (IOException e) { e.printStackTrace(); } } }
程序运行结果如下:
thread 0 start... thread0 bytes=0-46078 thread 1 start... thread1 bytes=46079-92157 thread 2 start... thread2 bytes=92158-138236 thread 3 start... thread3 bytes=138237-184319 thread2 bytes=92158-138236 thread 0 end. thread1 bytes=74995-92157 thread 1 end. thread3 bytes=174453-184319 thread 3 end. thread2 bytes=114648-138236 thread 2 end. U1565P1T557D132F12892DT20090425105719.jpg ok!
发表评论
-
设计模式-学习
2011-03-04 16:03 1203设计模式主要包含三个 ... -
SCA了解
2011-02-26 15:17 13671、在公司看到一个《SOA ... -
equals和hashcode
2011-02-21 22:11 1113import java.io.Serializable; p ... -
JXL时间类型处理
2010-10-20 15:15 6188JXL对于日期类型的处理,有些特殊需要注意: impo ... -
CLASS版本检测
2010-10-20 09:29 1457因为之前在试用jxl的时候,下载jexcelapi_2_6_1 ... -
jxl试用
2010-10-20 09:24 2783jxl的全称JExcelAPI,是一个读写修改EXCEL的JA ... -
POI之HSSF初探
2010-10-18 20:13 2081POI是APACHE出品的一个OFFICE文档操作类库,下面对 ... -
JSOUP初探
2010-10-18 14:47 12013JSOUP是偶然看到的一个处理HTML的JAVA 类库,其官方 ... -
文件切割(FILE SPLIT)
2010-07-23 09:11 2341package filesplit; import java ... -
JNDI使用测试
2010-07-15 18:22 1261package filesplit; import java ... -
快速读取文件行数
2010-07-15 12:07 10142package filesplit; import java ... -
数据库更新异常捕捉
2010-07-14 19:57 1136一般来说,数据库更新异常,可通过创建触发器来记录某一个关键字段 ... -
jdbc以服务名方式连接
2010-07-12 22:26 1162jdbc:oracle:thin:@(DESCRIPTION ... -
div 和 span的区别
2010-07-12 14:30 1132SPAN 和 DIV 的区别在于,DIV(division)是 ... -
(OS 10048)通常每个套接字地址 (协议/网络地址/端口) 只允许使用一次
2010-06-12 09:46 4469出现如下错误的解决办法: (OS 10048)通常每个 ... -
定时提醒测试
2010-06-11 18:19 1335package test; import java.util ... -
字符串压缩解压
2010-03-25 23:22 2984package test.compress; impor ... -
重写equals的方法
2009-10-13 21:38 9311.使用==操作符检 ... -
Exception处理的一个技巧
2009-10-13 21:35 965package test2; public class ... -
正则实现日期校验
2009-07-30 14:13 1116private void checkDate() throws ...
相关推荐
在Android开发中,多线程断点续传是一项重要的技术,尤其在处理大文件下载时。这个技术的主要目的是提高下载效率并确保用户可以中断或恢复下载过程。以下将详细讲解多线程断点续传的概念、实现原理以及在Android中的...
在Android应用开发中,实现多线程断点续传下载是一项重要的技术,它涉及到网络编程、文件操作以及并发处理等多个方面。以下将详细介绍这个主题的相关知识点。 首先,我们需要理解“多线程”。在Android系统中,为了...
标题中的“FTP、HTTP 多线程断点续传下载文件.rar”暗示了这是一个关于网络协议(FTP和HTTP)在实现多线程下载时如何支持断点续传功能的资源包。这个压缩文件可能包含了一个或者多个示例程序、文档或教程,用于解释...
在提供的压缩包文件中,可能包含了一个名为“download”的示例项目,这可能是用于演示上述多线程断点续传功能的源代码。通过分析和运行这个项目,你可以更直观地理解这两种技术的结合应用。 总之,多线程和断点续传...
Java多线程断点续传下载是一个复杂但实用的技术,尤其在处理大文件或网络不稳定时,能够提高用户体验并优化资源利用。以下是对这个主题的详细解析: **1. Java多线程** Java多线程是指在一个Java应用程序中同时执行...
而"多线程"和"断点"这两个文件名可能是指相关示例代码或文档,可以进一步帮助你理解和实践Java FTP的多线程下载和断点续传。 在实际应用中,还需要考虑其他因素,如错误处理、网络状况的监控、文件完整性检查等。...
在Android开发中,多线程断点续传下载是一项重要的技术,它允许用户在暂停、关闭应用或设备重启后从上次中断的地方继续下载大文件,提高用户体验并节省网络资源。以下将详细介绍这一技术的关键知识点: 1. **多线程...
在这个主题中,我们将专注于使用Xutils实现多线程断点续传的功能,这对于大文件下载尤其重要。 首先,断点续传是一种在网络不稳定或者设备意外断电的情况下,能够从上次中断的位置继续下载的技术。它通过保存已下载...
同时,"【成品】多线程断点续传工具.jar"可能是一个可执行的Java应用程序,它提供了用户界面或者命令行工具,让用户可以方便地进行断点续传的文件上传。 多线程断点续传进一步提高了文件传输的效率。通过将文件分割...
总结来说,Java实现的多线程断点续传涉及的技术点包括: 1. 并发编程:使用`ExecutorService`、`CountDownLatch`进行线程管理和同步。 2. 文件操作:分析和合并临时文件,实现断点续传。 3. 网络I/O:通过`...
在Android应用开发中,实现“多线程断点续传下载+在线播放音乐”涉及到多个关键技术,主要包括网络编程、文件操作、多线程处理、内存管理以及多媒体播放等。以下是对这些知识点的详细阐述: 1. **多线程下载**: ...
在Android开发中,多线程断点续传技术是一种提高下载效率并优化用户体验的重要方法。这一技术主要应用于大型文件的下载场景,如游戏、应用程序或高清视频等,它允许用户在下载过程中随时暂停,之后能从中断的地方...
在点对点网络中实现多线程断点续传,主要涉及以下几个关键技术点: 1. **网络连接与通信协议**:P2P网络通常使用TCP或UDP协议进行通信。TCP保证了数据的可靠传输,适合断点续传,而UDP则提供了更高的传输速度,但...
### Java实现FTP多线程断点续传:深入解析与技术要点 在现代软件开发中,数据传输是一项基本且关键的任务,特别是在处理大文件时,断点续传功能显得尤为重要。断点续传允许在网络连接中断后恢复传输,避免了重新...
在Android开发中,实现多线程断点续传下载网络上的音视频文件是一项重要的技能,尤其对于提升用户体验和节省用户流量至关重要。断点续传允许用户在暂停或因网络问题中断下载后,从上次停止的位置继续,而多线程则能...
在Android平台上,开发一款支持多线程断点续传功能的下载工具是一项技术挑战,它涉及到网络编程、文件处理以及线程管理等多个方面。这款名为"DownloadHelper"的项目,显然是一个致力于解决这些问题的开源解决方案。 ...
在安卓开发中,多线程断点续传是一项重要的技术,尤其在处理大文件下载时,它可以提高下载效率,同时确保在下载过程中如果中断,可以从上次停止的地方继续,避免了数据的重复下载。本文将详细讲解安卓多线程断点续传...