欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)的斷點(diǎn)續(xù)傳功能的示例代碼

 更新時(shí)間:2017年02月21日 08:22:34   作者:路代為說項(xiàng)  
本篇文章主要介紹了Java實(shí)現(xiàn)的斷點(diǎn)續(xù)傳功能的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

代碼中已經(jīng)加入了注釋,需要的朋友可以直接參考代碼中的注釋。下面直接上功能實(shí)現(xiàn)的主要代碼:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
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;

/*
 * Encode:UTF-8
 * 
 * Author:zhiming.xu
 * 
 * 多線程的斷點(diǎn)下載程序,根據(jù)輸入的url和指定線程數(shù),來完成斷點(diǎn)續(xù)傳功能。
 * 
 * 每個(gè)線程支負(fù)責(zé)某一小段的數(shù)據(jù)下載;再通過RandomAccessFile完成數(shù)據(jù)的整合。
 */
public class MultiTheradDownLoad {

  private String filepath = null;
  private String filename = null;
  private String tmpfilename = null;

  private int threadNum = 0;

  private CountDownLatch latch = null;//設(shè)置一個(gè)計(jì)數(shù)器,代碼內(nèi)主要用來完成對(duì)緩存文件的刪除

  private long fileLength = 0l;
  private long threadLength = 0l;
  private long[] startPos;//保留每個(gè)線程下載數(shù)據(jù)的起始位置。
  private long[] endPos;//保留每個(gè)線程下載數(shù)據(jù)的截止位置。

  private boolean bool = false;

  private URL url = null;

  //有參構(gòu)造函數(shù),先構(gòu)造需要的數(shù)據(jù)
  public MultiTheradDownLoad(String filepath, int threadNum) {
    this.filepath = filepath;
    this.threadNum = threadNum;
    startPos = new long[this.threadNum];
    endPos = new long[this.threadNum];
    latch = new CountDownLatch(this.threadNum);
  }

  /*
   * 組織斷點(diǎn)續(xù)傳功能的方法
   */
  public void downloadPart() {

    File file = null;
    File tmpfile = null;
    HttpURLConnection httpcon = null;

    //在請(qǐng)求url內(nèi)獲取文件資源的名稱;此處沒考慮文件名為空的情況,此種情況可能需使用UUID來生成一個(gè)唯一數(shù)來代表文件名。
    filename = filepath.substring(filepath.lastIndexOf('/') + 1, filepath
        .contains("?") ? filepath.lastIndexOf('?') : filepath.length());
    tmpfilename = filename + "_tmp";

    try {
      url = new URL(filepath);
      httpcon = (HttpURLConnection) url.openConnection();

      setHeader(httpcon);
      fileLength = httpcon.getContentLengthLong();//獲取請(qǐng)求資源的總長(zhǎng)度。

      file = new File(filename);
      tmpfile = new File(tmpfilename);

      threadLength = fileLength / threadNum;//每個(gè)線程需下載的資源大小。
      System.out.println("fileName: " + filename + " ," + "fileLength= "
          + fileLength + " the threadLength= " + threadLength);

      if (file.exists() && file.length() == fileLength) {
        System.out
            .println("the file you want to download has exited!!");
        return;
      } else {
        setBreakPoint(startPos, endPos, tmpfile);
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < threadNum; i++) {
          exec.execute(new DownLoadThread(startPos[i], endPos[i],
              this, i, tmpfile, latch));
        }
        latch.await();//當(dāng)你的計(jì)數(shù)器減為0之前,會(huì)在此處一直阻塞。
        exec.shutdown();
      }
    } catch (MalformedURLException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    if (file.length() == fileLength) {
      if (tmpfile.exists()) {
        System.out.println("delect the temp file!!");
        tmpfile.delete();
      }
    }
  }

  /*
   * 斷點(diǎn)設(shè)置方法,當(dāng)有臨時(shí)文件時(shí),直接在臨時(shí)文件中讀取上次下載中斷時(shí)的斷點(diǎn)位置。沒有臨時(shí)文件,即第一次下載時(shí),重新設(shè)置斷點(diǎn)。
   * 
   * rantmpfile.seek()跳轉(zhuǎn)到一個(gè)位置的目的是為了讓各個(gè)斷點(diǎn)存儲(chǔ)的位置盡量分開。
   * 
   * 這是實(shí)現(xiàn)斷點(diǎn)續(xù)傳的重要基礎(chǔ)。
   */
  private void setBreakPoint(long[] startPos, long[] endPos, File tmpfile) {
    RandomAccessFile rantmpfile = null;
    try {
      if (tmpfile.exists()) {
        System.out.println("the download has continued!!");
        rantmpfile = new RandomAccessFile(tmpfile, "rw");
        for (int i = 0; i < threadNum; i++) {
          rantmpfile.seek(8 * i + 8);
          startPos[i] = rantmpfile.readLong();

          rantmpfile.seek(8 * (i + 1000) + 16);
          endPos[i] = rantmpfile.readLong();

          System.out.println("the Array content in the exit file: ");
          System.out.println("thre thread" + (i + 1) + " startPos:"
              + startPos[i] + ", endPos: " + endPos[i]);
        }
      } else {
        System.out.println("the tmpfile is not available!!");
        rantmpfile = new RandomAccessFile(tmpfile, "rw");
        
        //最后一個(gè)線程的截止位置大小為請(qǐng)求資源的大小
        for (int i = 0; i < threadNum; i++) {
          startPos[i] = threadLength * i;
          if (i == threadNum - 1) {
            endPos[i] = fileLength;
          } else {
            endPos[i] = threadLength * (i + 1) - 1;
          }

          rantmpfile.seek(8 * i + 8);
          rantmpfile.writeLong(startPos[i]);

          rantmpfile.seek(8 * (i + 1000) + 16);
          rantmpfile.writeLong(endPos[i]);

          System.out.println("the Array content: ");
          System.out.println("thre thread" + (i + 1) + " startPos:"
              + startPos[i] + ", endPos: " + endPos[i]);
        }
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (rantmpfile != null) {
          rantmpfile.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
  
  /*
   * 實(shí)現(xiàn)下載功能的內(nèi)部類,通過讀取斷點(diǎn)來設(shè)置向服務(wù)器請(qǐng)求的數(shù)據(jù)區(qū)間。
   */
  class DownLoadThread implements Runnable {

    private long startPos;
    private long endPos;
    private MultiTheradDownLoad task = null;
    private RandomAccessFile downloadfile = null;
    private int id;
    private File tmpfile = null;
    private RandomAccessFile rantmpfile = null;
    private CountDownLatch latch = null;

    public DownLoadThread(long startPos, long endPos,
        MultiTheradDownLoad task, int id, File tmpfile,
        CountDownLatch latch) {
      this.startPos = startPos;
      this.endPos = endPos;
      this.task = task;
      this.tmpfile = tmpfile;
      try {
        this.downloadfile = new RandomAccessFile(this.task.filename,
            "rw");
        this.rantmpfile = new RandomAccessFile(this.tmpfile, "rw");
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      }
      this.id = id;
      this.latch = latch;
    }

    @Override
    public void run() {

      HttpURLConnection httpcon = null;
      InputStream is = null;
      int length = 0;

      System.out.println("the thread " + id + " has started!!");

      while (true) {
        try {
          httpcon = (HttpURLConnection) task.url.openConnection();
          setHeader(httpcon);
          
          //防止網(wǎng)絡(luò)阻塞,設(shè)置指定的超時(shí)時(shí)間;單位都是ms。超過指定時(shí)間,就會(huì)拋出異常
          httpcon.setReadTimeout(20000);//讀取數(shù)據(jù)的超時(shí)設(shè)置
          httpcon.setConnectTimeout(20000);//連接的超時(shí)設(shè)置

          if (startPos < endPos) {
            
            //向服務(wù)器請(qǐng)求指定區(qū)間段的數(shù)據(jù),這是實(shí)現(xiàn)斷點(diǎn)續(xù)傳的根本。
            httpcon.setRequestProperty("Range", "bytes=" + startPos
                + "-" + endPos);

            System.out
                .println("Thread " + id
                    + " the total size:---- "
                    + (endPos - startPos));

            downloadfile.seek(startPos);

            if (httpcon.getResponseCode() != HttpURLConnection.HTTP_OK
                && httpcon.getResponseCode() != HttpURLConnection.HTTP_PARTIAL) {
              this.task.bool = true;
              httpcon.disconnect();
              downloadfile.close();
              System.out.println("the thread ---" + id
                  + " has done!!");
              latch.countDown();//計(jì)數(shù)器自減
              break;
            }

            is = httpcon.getInputStream();//獲取服務(wù)器返回的資源流
            long count = 0l;
            byte[] buf = new byte[1024];

            while (!this.task.bool && (length = is.read(buf)) != -1) {
              count += length;
              downloadfile.write(buf, 0, length);
              
              //不斷更新每個(gè)線程下載資源的起始位置,并寫入臨時(shí)文件;為斷點(diǎn)續(xù)傳做準(zhǔn)備
              startPos += length;
              rantmpfile.seek(8 * id + 8);
              rantmpfile.writeLong(startPos);
            }
            System.out.println("the thread " + id
                + " total load count: " + count);
            
            //關(guān)閉流
            is.close();
            httpcon.disconnect();
            downloadfile.close();
            rantmpfile.close();
          }
          latch.countDown();//計(jì)數(shù)器自減
          System.out.println("the thread " + id + " has done!!");
          break;
        } catch (IOException e) {
          e.printStackTrace();
        } finally {
          try {
            if (is != null) {
              is.close();
            }
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }

  /*
   * 為一個(gè)HttpURLConnection模擬請(qǐng)求頭,偽裝成一個(gè)瀏覽器發(fā)出的請(qǐng)求
   */
  private void setHeader(HttpURLConnection con) {
    con.setRequestProperty(
        "User-Agent",
        "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3");
    con.setRequestProperty("Accept-Language", "en-us,en;q=0.7,zh-cn;q=0.3");
    con.setRequestProperty("Accept-Encoding", "aa");
    con.setRequestProperty("Accept-Charset",
        "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
    con.setRequestProperty("Keep-Alive", "300");
    con.setRequestProperty("Connection", "keep-alive");
    con.setRequestProperty("If-Modified-Since",
        "Fri, 02 Jan 2009 17:00:05 GMT");
    con.setRequestProperty("If-None-Match", "\"1261d8-4290-df64d224\"");
    con.setRequestProperty("Cache-Control", "max-age=0");
    con.setRequestProperty("Referer",
        "http://www.skycn.com/soft/14857.html");
  }
}

下面是測(cè)試代碼:

public class DownLoadTest {

  /**
   * @param args
   */
  public static void main(String[] args) {
    
    String filepath = "http://127.0.0.1:8080/file/loadfile.mkv";
    MultiTheradDownLoad load = new MultiTheradDownLoad(filepath ,4);  
    load.downloadPart();  
  }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java數(shù)據(jù)結(jié)構(gòu)之樹基本概念解析及代碼示例

    java數(shù)據(jù)結(jié)構(gòu)之樹基本概念解析及代碼示例

    這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)之樹基本概念解析及代碼示例,介紹了樹的定義,基本術(shù)語,主要操作及實(shí)現(xiàn)等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可了解下。
    2017-11-11
  • SpringBoot利用自定義json序列化器實(shí)現(xiàn)敏感字段數(shù)據(jù)脫敏詳解

    SpringBoot利用自定義json序列化器實(shí)現(xiàn)敏感字段數(shù)據(jù)脫敏詳解

    這篇文章主要介紹了SpringBoot利用自定義json序列化器實(shí)現(xiàn)敏感字段數(shù)據(jù)脫敏詳解,因?yàn)榘咐a用到了hutool提供的DesensitizedUtil數(shù)據(jù)脫敏工具類,這里要引入hutool的依賴,如果你需要自定義 數(shù)據(jù)脫敏的邏輯,可以不引入這個(gè)依賴,需要的朋友可以參考下
    2024-01-01
  • Springboot 實(shí)現(xiàn)數(shù)據(jù)庫備份還原的方法

    Springboot 實(shí)現(xiàn)數(shù)據(jù)庫備份還原的方法

    這篇文章主要介紹了Springboot 實(shí)現(xiàn)數(shù)據(jù)庫備份還原的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Java實(shí)現(xiàn)二維數(shù)組和稀疏數(shù)組之間的轉(zhuǎn)換

    Java實(shí)現(xiàn)二維數(shù)組和稀疏數(shù)組之間的轉(zhuǎn)換

    本文主要介紹了Java 二維數(shù)組和稀疏數(shù)組轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • Java中的DelayQueue源碼解析

    Java中的DelayQueue源碼解析

    這篇文章主要介紹了Java中的DelayQueue源碼解析,一個(gè)實(shí)現(xiàn)PriorityBlockingQueue實(shí)現(xiàn)延遲獲取的無界隊(duì)列,在創(chuàng)建元素時(shí),可以指定多久才能從隊(duì)列中獲取當(dāng)前元素,只有延時(shí)期滿后才能從隊(duì)列中獲取元素,需要的朋友可以參考下
    2023-12-12
  • Java基礎(chǔ)第五篇 實(shí)施接口

    Java基礎(chǔ)第五篇 實(shí)施接口

    在public和private的封裝機(jī)制,我們實(shí)際上同時(shí)定義了類和接口,類和接口混合在一起。Java還提供了interface這一語法。這一語法將接口從類的具體定義中剝離出來,構(gòu)成一個(gè)獨(dú)立的主體,下面文章內(nèi)容將為大家做詳細(xì)介紹
    2021-09-09
  • 一文帶你全面了解Java?Properties類

    一文帶你全面了解Java?Properties類

    Properties是JDK1.0中引入的java類,目前也在項(xiàng)目中大量使用,主要用來讀取外部的配置,那除了這個(gè),你對(duì)它其他的一些api也了解嗎??你了解它是怎么實(shí)現(xiàn)的嗎??如果不清楚的話,就通過本篇文章帶你一探究竟
    2022-09-09
  • springboot2.x集成swagger的方法示例

    springboot2.x集成swagger的方法示例

    這篇文章主要介紹了springboot2.x集成swagger的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 如何將Object類轉(zhuǎn)換為實(shí)體類

    如何將Object類轉(zhuǎn)換為實(shí)體類

    這篇文章主要介紹了如何將Object類轉(zhuǎn)換為實(shí)體類,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • java實(shí)現(xiàn)簡(jiǎn)單單鏈表

    java實(shí)現(xiàn)簡(jiǎn)單單鏈表

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單單鏈表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-02-02

最新評(píng)論