首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 實現斷點續傳下載:基於 RandomAccessFile 的實戰代碼

     編輯:Java 綜合教學

Java 實現斷點續傳下載:基於 RandomAccessFile 的實戰代碼

核心原理

斷點續傳的核心思想:記錄已下載的文件位置(斷點),下次下載時從該位置繼續,而非重頭開始。Java 中通過 RandomAccessFile 實現,關鍵方法:

  • seek(long pos):移動文件指針到指定位置
  • getFilePointer():獲取當前文件指針位置
  • setLength(long len):設置文件長度(預分配空間)

完整實現代碼

package com.dragon.java.downloadfile;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class ResumeDownloadDemo {
    public static void main(String[] args) {
        File srcFile = new File("D:/Java4Android/01_Java考古學/01_Java考古學.mp4");
        File desDir = new File("f:/vidio");
        copyFileWithResume(srcFile, desDir);
    }

    public static void copyFileWithResume(File srcFile, File desDir) {
        desDir.mkdirs();
        
        // 配置文件:記錄斷點位置
        File configFile = new File(desDir, srcFile.getName().split("\\.")[0] + ".config");
        // 目標文件
        File desFile = new File(desDir, srcFile.getName());
        
        // 若無配置文件但目標文件存在,視為已下載完成
        if (!configFile.exists() && desFile.exists()) {
            System.out.println("文件已下載完成!");
            return;
        }

        RandomAccessFile rafSrc = null;
        RandomAccessFile rafDes = null;
        RandomAccessFile rafConfig = null;
        
        try {
            rafSrc = new RandomAccessFile(srcFile, "r");
            rafDes = new RandomAccessFile(desFile, "rw");
            rafConfig = new RandomAccessFile(configFile, "rw");
            
            // 預分配目標文件空間,避免寫入時擴容開銷
            rafDes.setLength(srcFile.length());
            // 配置文件固定 8 字節(存一個 long),預防首次讀取 EOF 異常
            rafConfig.setLength(8);
            
            // 讀取上次下載位置
            long pointer = rafConfig.readLong();
            System.out.printf("已下載:%.2f%%%n", (float) pointer / srcFile.length() * 100);
            
            // 移動源/目標文件指針到斷點位置
            rafSrc.seek(pointer);
            rafDes.seek(pointer);
            
            // 小緩衝區便於觀察斷點續傳效果,生產環境建議 4KB-8KB
            byte[] buffer = new byte[32];
            int len;
            
            while ((len = rafSrc.read(buffer)) != -1) {
                rafDes.write(buffer, 0, len);
                
                // 關鍵:每次寫入後立即記錄最新指針位置
                rafConfig.seek(0);  // 重置配置文件指針到開頭
                rafConfig.writeLong(rafSrc.getFilePointer());  // 記錄最新位置
            }
            
            System.out.println("下載成功!");
            
        } catch (IOException e) {
            System.out.println("下載中斷:" + e.getMessage());
        } finally {
            // 安全關閉流
            closeQuietly(rafSrc);
            closeQuietly(rafDes);
            closeQuietly(rafConfig);
            
            // 下載完成後刪除配置文件
            if (configFile.exists()) configFile.delete();
        }
    }
    
    private static void closeQuietly(RandomAccessFile raf) {
        if (raf != null) {
            try { raf.close(); } catch (IOException ignored) {}
        }
    }
}

關鍵設計細節解析

  1. 配置文件機制:使用固定 8 字節文件存儲 long 類型的斷點位置,每次寫入前 seek(0) 覆蓋舊值,確保隨時可恢復
  2. 預分配空間:rafDes.setLength(srcFile.length()) 避免寫入過程中頻繁擴容,提升性能
  3. 異常安全:finally 區塊確保流關閉,中斷時配置文件已記錄最新進度
  4. 完成標記:下載完成刪除配置文件,下次運行直接判定為已完成

生產環境優化建議

  • 緩衝區大小調整為 4KB-8KB(new byte[8192])
  • 增加下載速度限制、進度回調接口
  • 支持多線程分塊下載(需服務端支持 Range 請求)
  • 校驗文件完整性(MD5/SHA1)

這個 Demo 通過本地文件複製模擬了斷點續傳的核心邏輯,網絡下載場景下只需將 rafSrc 替換為 HttpURLConnection 或 OkHttp 的輸入流即可,核心斷點邏輯完全一致。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved