java實(shí)現(xiàn)多線程文件的斷點(diǎn)續(xù)傳
java文件的多線程斷點(diǎn)續(xù)傳大致原理,供大家參考,具體內(nèi)容如下
談到文件斷點(diǎn)續(xù)傳那么就離不開java.io.RandomAcessFile HttpUrlConnection類
大致思路如下:
1、HttpUrlConnection去請(qǐng)求服務(wù)器 獲得文件的長(zhǎng)度con.getContentLength()
2、創(chuàng)建一個(gè)空的RandomAcessFile來(lái)接收,并且指定剛剛獲取的長(zhǎng)度setLength
3、開啟N個(gè)線程 計(jì)算每個(gè)線程需要下載的長(zhǎng)度
4、獲取之前先去看看下載的進(jìn)度保存文件是否存在 如果存在就從文件里獲取已經(jīng)下載的進(jìn)度
5、開始文件下載
6、臨時(shí)文件的刪除 資源的關(guān)閉
下面貼出完整代碼
package demo; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; class MultiDownloaFile { ? ? public static final String path = "http://192.168.217.1:8080/androidsimpleserver/HTTP.pdf"; ? ? public static final int TOTAL_THREAD_COUNT = 3; ? ? public static int runningThreadCount = 0; ? ? public static void main(String[] args) { ? ? ? ? try { ? ? ? ? ? ? long start = System.currentTimeMillis(); ? ? ? ? ? ? URL url = new URL(path); ? ? ? ? ? ? HttpURLConnection conn = (HttpURLConnection) url.openConnection(); ? ? ? ? ? ? conn.setRequestMethod("GET"); ? ? ? ? ? ? int code = conn.getResponseCode(); ? ? ? ? ? ? if (code == 200) { ? ? ? ? ? ? ? ? int length = conn.getContentLength(); ? ? ? ? ? ? ? ? System.out.println("file length:" + length); ? ? ? ? ? ? ? ? //create ?a ?null ?file ?to ?save ?its ?length ? ? ? ? ? ? ? ? RandomAccessFile raf = new RandomAccessFile(getDownloadFileName(path), "rw"); ? ? ? ? ? ? ? ? raf.setLength(length); ? ? ? ? ? ? ? ? raf.close(); ? ? ? ? ? ? ? ? //parse ?every ?thread ?that ?they ?need ?how ?much ?room ?to ?download ? ? ? ? ? ? ? ? int blockSize = length / TOTAL_THREAD_COUNT; ? ? ? ? ? ? ? ? System.out.println("every block size:" + blockSize); ? ? ? ? ? ? ? ? runningThreadCount = TOTAL_THREAD_COUNT; ? ? ? ? ? ? ? ? for (int threadId = 0; threadId < TOTAL_THREAD_COUNT; threadId++) { ? ? ? ? ? ? ? ? ? ? int startPosition = threadId * blockSize; ? ? ? ? ? ? ? ? ? ? int endPosition = (threadId + 1) * blockSize - 1; ? ? ? ? ? ? ? ? ? ? if (threadId == (TOTAL_THREAD_COUNT - 1)) { ? ? ? ? ? ? ? ? ? ? ? ? endPosition = length - 1; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? System.out.println("thread::" + threadId + " download range:" + startPosition + "~~" + endPosition); ? ? ? ? ? ? ? ? ? ? //start thread ?to ?download ? ? ? ? ? ? ? ? ? ? new DownloadThread(threadId, startPosition, endPosition).start(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? System.out.println(" connection ?error "); ? ? ? ? ? ? } ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? } ? ? /** ? ? ?* 從網(wǎng)絡(luò)路徑獲取文件名 ? ? ?* ? ? ?* @param path 網(wǎng)絡(luò)路徑 ? ? ?* @return 文件名 ? ? ?*/ ? ? private static String getDownloadFileName(String path) { ? ? ? ? return path.substring(path.lastIndexOf("/") + 1); ? ? } ? ? /** ? ? ?* 下載文件的線程 ? ? ?*/ ? ? private static class DownloadThread extends Thread { ? ? ? ? /** ? ? ? ? ?* 線程id ? ? ? ? ?*/ ? ? ? ? private int threadId; ? ? ? ? /** ? ? ? ? ?* 當(dāng)前線程下載的起始位置 ? ? ? ? ?*/ ? ? ? ? private int startPosition; ? ? ? ? /** ? ? ? ? ?* 當(dāng)前線程下載的終止位置 ? ? ? ? ?*/ ? ? ? ? private int endPosition; ? ? ? ? public DownloadThread(int threadId, int startPosition, int endPosition) { ? ? ? ? ? ? this.threadId = threadId; ? ? ? ? ? ? this.startPosition = startPosition; ? ? ? ? ? ? this.endPosition = endPosition; ? ? ? ? } ? ? ? ? @Override ? ? ? ? public void run() { ? ? ? ? ? ? System.out.println("thread:" + threadId + " begin working"); ? ? ? ? ? ? // lest thread download it's self range data ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? File finfo = new File(TOTAL_THREAD_COUNT + getDownloadFileName(path) + threadId + ".txt"); // ? ? ? ? ? ? ? ?斷點(diǎn)續(xù)傳 ? ? ? ? ? ? ? ? if (finfo.exists() && finfo.length() > 0) { ? ? ? ? ? ? ? ? ? ? System.out.println(" 斷點(diǎn)續(xù)傳開始"); ? ? ? ? ? ? ? ? ? ? FileInputStream fis = new FileInputStream(finfo); ? ? ? ? ? ? ? ? ? ? BufferedReader br = new BufferedReader(new InputStreamReader(fis)); ? ? ? ? ? ? ? ? ? ? String lastPosition = br.readLine(); ? ? ? ? ? ? ? ? ? ? // This thread download data before times; ? ? ? ? ? ? ? ? ? ? int intLastPosition = Integer.parseInt(lastPosition); ? ? ? ? ? ? ? ? ? ? startPosition = intLastPosition; ? ? ? ? ? ? ? ? ? ? fis.close(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? URL url = new URL(path); ? ? ? ? ? ? ? ? HttpURLConnection conn = (HttpURLConnection) url.openConnection(); ? ? ? ? ? ? ? ? conn.setRequestMethod("GET"); ? ? ? ? ? ? ? ? System.out.println("begin and end:" + threadId + " range of download: " + startPosition + "~~" + endPosition); ? ? ? ? ? ? ? ? conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition); ? ? ? ? ? ? ? ? // Download Resource from server ? ? ? ? ? ? ? ? int code = conn.getResponseCode(); ? ? ? ? ? ? ? ? if (code == 206) { ? ? ? ? ? ? ? ? ? ? InputStream is = conn.getInputStream(); // ? ? ? ? ? ? ? ? ? ?RandomAccessFile raf = new RandomAccessFile(getDownloadFileName(path), "rw"); ? ? ? ? ? ? ? ? ? ? RandomAccessFile raf = new RandomAccessFile(getDownloadFileName(path), "rw"); ? ? ? ? ? ? ? ? ? ? // vary important, position of begin to write ? ? ? ? ? ? ? ? ? ? raf.seek(startPosition); ? ? ? ? ? ? ? ? ? ? byte[] buffer = new byte[1024 * 100]; ? ? ? ? ? ? ? ? ? ? int len = -1; ? ? ? ? ? ? ? ? ? ? int total = 0; // downloaded data of current thread in this times; ? ? ? ? ? ? ? ? ? ? while ((len = is.read(buffer)) != -1) { ? ? ? ? ? ? ? ? ? ? ? ? raf.write(buffer, 0, len); ? ? ? ? ? ? ? ? ? ? ? ? // record position of current thread to downloading ? ? ? ? ? ? ? ? ? ? ? ? total += len; ? ? ? ? ? ? ? ? ? ? ? ? RandomAccessFile inforaf = new RandomAccessFile(TOTAL_THREAD_COUNT + getDownloadFileName(path) + threadId + ".txt", "rwd"); ? ? ? ? ? ? ? ? ? ? ? ? // save position of current thread ? ? ? ? ? ? ? ? ? ? ? ? inforaf.write(String.valueOf(startPosition + total).getBytes()); ? ? ? ? ? ? ? ? ? ? ? ? inforaf.close(); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? is.close(); ? ? ? ? ? ? ? ? ? ? raf.close(); ? ? ? ? ? ? ? ? ? ? System.out.println("thread:" + threadId + " download complete..."); ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? System.out.println("request download failed."); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? } finally { ? ? ? ? ? ? ? ? synchronized (MultiDownloaFile.class) { ? ? ? ? ? ? ? ? ? ? runningThreadCount--; ? ? ? ? ? ? ? ? ? ? if (runningThreadCount <= 0) { ? ? ? ? ? ? ? ? ? ? ? ? System.out.println(" ?all ?multi thread download complete. ? success!!!"); ? ? ? ? ? ? ? ? ? ? ? ? for (int i = 0; i < TOTAL_THREAD_COUNT; i++) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? File finfo = new File(TOTAL_THREAD_COUNT + getDownloadFileName(path) + i + ".txt"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? System.out.println(finfo.delete()); ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot 功能整合的實(shí)現(xiàn)
Spring Boot生態(tài)豐富,集成也不算困難。本文簡(jiǎn)單的介紹下功能整合的步驟,最后提供一個(gè)具體的實(shí)現(xiàn)例子,學(xué)習(xí)Spring Boot的同學(xué)可以參考下2021-05-05springboot集成RestTemplate及常見的用法說(shuō)明
這篇文章主要介紹了springboot集成RestTemplate及常見的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10重新對(duì)Java的類加載器的學(xué)習(xí)方式
這篇文章主要介紹了重新對(duì)Java的類加載器的學(xué)習(xí)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-05-05springboot登陸過濾功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了springboot登陸過濾功能的實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-12-12Java使用新浪微博API開發(fā)微博應(yīng)用的基本方法
這篇文章主要介紹了Java使用新浪微博API開發(fā)微博應(yīng)用的基本方法,文中還給出了一個(gè)不使用任何SDK實(shí)現(xiàn)Oauth授權(quán)并實(shí)現(xiàn)簡(jiǎn)單的發(fā)布微博功能的實(shí)現(xiàn)方法,需要的朋友可以參考下2015-11-11JPA設(shè)置默認(rèn)字段及其長(zhǎng)度詳解
JPA是Java Persistence API的簡(jiǎn)稱,中文名Java持久層API,是JDK 5.0注解或XML描述對(duì)象-關(guān)系表的映射關(guān)系,并將運(yùn)行期的實(shí)體對(duì)象持久化到數(shù)據(jù)庫(kù)中。本文主要介紹了JPA如何設(shè)置默認(rèn)字段及其長(zhǎng)度,感興趣的同學(xué)可以了解一下2021-12-12SpringBoot基于Actuator遠(yuǎn)程關(guān)閉服務(wù)
這篇文章主要介紹了SpringBoot基于Actuator遠(yuǎn)程關(guān)閉服務(wù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11Springboot如何同時(shí)裝配兩個(gè)相同類型數(shù)據(jù)庫(kù)
這篇文章主要介紹了Springboot如何同時(shí)裝配兩個(gè)相同類型數(shù)據(jù)庫(kù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11