java断点下载

忘了在哪里抄的这东西了,发上来由兴趣的可以去研究一下

 

 public class Task { 
  
  
  
   private String downURL; 
  
  
  
   private String saveFile; 
  
    
  
   private int bufferSize = 64 * 1024; 
  
    
  
   private int workerCount; 
  
    
  
   private int sectionCount; 
  
    
  
   private long contentLength; 
  
    
  
   private long[] sectionsOffset; 
  
    
  
   public static final int HEAD_SIZE = 4096; 
  
    
  
   //读下载描述文件内容 
  
   public synchronized void read(RandomAccessFile file) throws IOException { 
  
     byte[] temp = new byte[HEAD_SIZE]; 
  
     file.seek(0); 
  
     int readed = file.read(temp); 
  
     if (readed != temp.length) { 
  
       throw new RuntimeException(); 
  
     } 
  
     ByteArrayInputStream bais = new ByteArrayInputStream(temp); 
  
     DataInputStream dis = new DataInputStream(bais); 
  
     downURL = dis.readUTF(); 
  
     saveFile = dis.readUTF(); 
  
     sectionCount = dis.readInt(); 
  
     contentLength = dis.readLong(); 
  
      
  
     sectionsOffset = new long[sectionCount]; 
  
     for (int i = 0; i < sectionCount; i++) { 
  
       sectionsOffset[i] = file.readLong(); 
  
     } 
  
   } 
  
    
  
   //创建下载描述文件内容 
  
   public synchronized void create(RandomAccessFile file) throws IOException { 
  
     if (sectionCount != sectionsOffset.length) { 
  
       throw new RuntimeException(); 
  
     } 
  
     long len = HEAD_SIZE + 8 * sectionCount; 
  
     file.setLength(len); 
  
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
  
     DataOutputStream dos = new DataOutputStream(baos); 
  
     dos.writeUTF(downURL); 
  
     dos.writeUTF(saveFile); 
  
     dos.writeInt(sectionCount); 
  
     dos.writeLong(contentLength); 
  
     byte[] src = baos.toByteArray(); 
  
     byte[] temp = new byte[HEAD_SIZE]; 
  
     System.arraycopy(src, 0, temp, 0, src.length); 
  
     file.seek(0); 
  
     file.write(temp); 
  
     writeOffset(file); 
  
   } 
  
    
  
   //更新下载的过程 
  
   public synchronized void writeOffset(RandomAccessFile file) throws IOException { 
  
     if (sectionCount != sectionsOffset.length) { 
  
       throw new RuntimeException(); 
  
     } 
  
     file.seek(HEAD_SIZE); 
  
     for (int i = 0; i < sectionsOffset.length; i++) { 
  
       file.writeLong(sectionsOffset[i]); 
  
     } 
  
   } 
  
   (下面是Getter、Setter) 
  
 } 
  
  
  
 //这个是下载主程序 
  
  
  
 public class TaskAssign { 
  
  
  
   public void work(Task task) throws IOException { 
  
     File file = new File(task.getSaveFile()); 
  
     if (file.exists()) { 
  
       return; 
  
     } 
  
     //这个是记录是否下载成功。我这里也没有增加失败回复、重试之类的工作。 
  
     final AtomicBoolean success = new AtomicBoolean(true); 
  
     //任务描述文件 
  
     File taskFile = new File(task.getSaveFile() + ".r_task"); 
  
     //真正下载的文件 
  
     File saveFile = new File(task.getSaveFile() + ".r_save"); 
  
     boolean taskFileExist = taskFile.exists(); 
  
     RandomAccessFile taskRandomFile = null; 
  
     RandomAccessFile downRandomFile = null; 
  
     try { 
  
       taskRandomFile = new RandomAccessFile(taskFile, "rw"); 
  
       downRandomFile = new RandomAccessFile(saveFile, "rw"); 
  
       long rtnLen = getContentLength(task.getDownURL()); 
  
       if (!taskFileExist) { 
  
         //如果文件不存在,就初始化任务文件和下载文件 
  
         task.setContentLength(rtnLen); 
  
         initTaskFile(taskRandomFile, task); 
  
         downRandomFile.setLength(rtnLen); 
  
       } else { 
  
         //任务文件存在就读取任务文件 
  
         task.read(taskRandomFile); 
  
         if (task.getContentLength() != rtnLen) { 
  
           throw new RuntimeException(); 
  
         } 
  
       } 
  
       int secCount = task.getSectionCount(); 
  
       //分配线程去下载,这里用到线程池 
  
       ExecutorService es = Executors.newFixedThreadPool(task.getWorkerCount()); 
  
       for (int i = 0; i < secCount; i++) { 
  
         final int j = i; 
  
         final Task t = task; 
  
         final RandomAccessFile f1 = taskRandomFile; 
  
         final RandomAccessFile f2 = downRandomFile; 
  
         es.execute(new Runnable() { 
  
           public void run() { 
  
             try { 
  
               down(f1, f2, t, j); 
  
             } catch (IOException e) { 
  
               success.set(false); 
  
               e.printStackTrace(System.out); 
  
             } 
  
           } 
  
         }); 
  
       } 
  
       es.shutdown(); 
  
       try { 
  
         es.awaitTermination(24 * 3600, TimeUnit.SECONDS); 
  
       } catch (InterruptedException e) { 
  
         e.printStackTrace(); 
  
       } 
  
       taskRandomFile.close(); 
  
       taskRandomFile = null; 
  
       downRandomFile.close(); 
  
       downRandomFile = null; 
  
       //如果下载成功,去掉任务描述文件、帮下载文件改名 
  
       if (success.get()) { 
  
         taskFile.delete(); 
  
         saveFile.renameTo(file); 
  
       } 
  
     } finally { 
  
       if (taskRandomFile != null) { 
  
         taskRandomFile.close(); 
  
         taskRandomFile = null; 
  
       } 
  
       if (downRandomFile != null) { 
  
         downRandomFile.close(); 
  
         downRandomFile = null; 
  
       } 
  
     } 
  
   } 
  
    
  
   public void down(RandomAccessFile taskRandomFile, RandomAccessFile downRandomFile, Task task, int sectionNo) throws IOException { 
  
     //这里我用HttpURLConnection下载,你也可以用HttpClient或者自己实现一个Http协议(不过貌似没有必要) 
  
     URL u = new URL(task.getDownURL()); 
  
     HttpURLConnection conn = (HttpURLConnection) u.openConnection(); 
  
     long start = task.getSectionsOffset()[sectionNo]; 
  
     long end = -1; 
  
     //这里要注意一下,这里是计算当前块的长度 
  
     if (sectionNo < task.getSectionCount() - 1) { 
  
       long per = task.getContentLength() / task.getSectionCount(); 
  
       end = per * (sectionNo + 1); 
  
     } else { 
  
       end = task.getContentLength(); 
  
     } 
  
     if (start >= end) { 
  
       System.out.println("Section has finished before. " + sectionNo); 
  
       return; 
  
     } 
  
     String range = "bytes=" + start + "-" + (end - 1); 
  
     conn.setRequestProperty("Range", range); 
  
     conn.setRequestProperty("User-Agent", "Ray-Downer"); 
  
     try { 
  
       conn.connect(); 
  
       if (conn.getResponseCode() != 206) { 
  
         throw new RuntimeException(); 
  
       } 
  
       if (conn.getContentLength() != (end - start)) { 
  
         throw new RuntimeException(); 
  
       } 
  
       InputStream is = conn.getInputStream(); 
  
       byte[] temp = new byte[task.getBufferSize()]; 
  
       BufferedInputStream bis = new BufferedInputStream(is, temp.length); 
  
       int readed = 0; 
  
       while ((readed = bis.read(temp)) > 0) { 
  
         long offset = task.getSectionsOffset()[sectionNo]; 
  
         synchronized (task) { 
  
           //下载之后顺便更新描述文件,你可能会发现这里效率比较低,在一个线程同步里进行两次文件操作。你可以自己实现一个缓冲写。 
  
           downRandomFile.seek(offset); 
  
           downRandomFile.write(temp, 0, readed); 
  
           offset += readed; 
  
           task.getSectionsOffset()[sectionNo] = offset; 
  
           task.writeOffset(taskRandomFile); 
  
         } 
  
       } 
  
     } finally { 
  
       conn.disconnect(); 
  
     } 
  
     System.out.println("Section finished. " + sectionNo); 
  
   } 
  
    
  
   public void initTaskFile(RandomAccessFile taskRandomFile, Task task) throws IOException { 
  
     int secCount = task.getSectionCount(); 
  
     long per = task.getContentLength() / secCount; 
  
     long[] sectionsOffset = new long[secCount]; 
  
     for (int i = 0; i < secCount; i++) { 
  
       sectionsOffset[i] = per * i; 
  
     } 
  
     task.setSectionsOffset(sectionsOffset); 
  
     task.create(taskRandomFile); 
  
   } 
  
    
  
   public long getContentLength(String url) throws IOException { 
  
     URL u = new URL(url); 
  
     HttpURLConnection conn = (HttpURLConnection) u.openConnection(); 
  
     try { 
  
       return conn.getContentLength(); 
  
     } finally { 
  
       conn.disconnect(); 
  
     } 
  
   } 
  
 } 
  
  
  
 //稍微测试一下。 
  
 public class Main { 
  
    
  
   public static void main(String[] args) throws IOException { 
  
     test3(); 
  
     System.out.println("\n\n===============\nFinished."); 
  
   } 
  
   
  
   public static void test1() throws IOException { 
  
     Task task = new Task(); 
  
     task.setDownURL("http://61.152.235.21/qqfile/qq/2007iistable/QQ2007IIKB1.exe"); 
  
     task.setSaveFile("H:/Test2.exe"); 
  
     task.setSectionCount(200); 
  
     task.setWorkerCount(100); 
  
     task.setBufferSize(256 * 1024); 
  
     TaskAssign ta = new TaskAssign(); 
  
     ta.work(task); 
  
   } 
  
    
  
   public static void test2() throws IOException { 
  
     Task task = new Task(); 
  
     task.setDownURL("http://student1.scut.edu.cn:8880/manage/news/data/1208421861893.xls"); 
  
     task.setSaveFile("H:/Test3.xls"); 
  
     task.setSectionCount(5); 
  
     task.setWorkerCount(1); 
  
     task.setBufferSize(128 * 1024); 
  
     TaskAssign ta = new TaskAssign(); 
  
     ta.work(task); 
  
   } 
  
    
  
   public static void test3() throws IOException { 
  
     Task task = new Task(); 
  
     task.setDownURL("http://go.microsoft.com/fwlink/?linkid=57034"); 
  
     task.setSaveFile("H:/vc2005express.iso"); 
  
     task.setSectionCount(500); 
  
     task.setWorkerCount(200); 
  
     task.setBufferSize(128 * 1024); 
  
     TaskAssign ta = new TaskAssign(); 
  
     ta.work(task); 
  
   } 
  
    
  
   public static void test4() throws IOException { 
  
     Task task = new Task(); 
  
     task.setDownURL("http://down.sandai.net/Thunder5.7.9.472.exe"); 
  
     task.setSaveFile("H:/Thunder.exe"); 
  
     task.setSectionCount(30); 
  
     task.setWorkerCount(30); 
  
     task.setBufferSize(128 * 1024); 
  
     TaskAssign ta = new TaskAssign(); 
  
     ta.work(task); 
  
   } 
  
 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值