1. 程式人生 > 程式設計 >Java檔案斷點續傳實現原理解析

Java檔案斷點續傳實現原理解析

一、作用:

隨機流(RandomAccessFile)不屬於IO流,支援對檔案的讀取和寫入隨機訪問。

二、隨機訪問檔案原理:

首先把隨機訪問的檔案物件看作儲存在檔案系統中的一個大型 byte 陣列,然後通過指向該 byte 陣列的游標或索引(即:檔案指標 FilePointer)在該陣列任意位置讀取或寫入任意資料。

三、相關方法說明:

1、物件宣告:RandomAccessFile raf = newRandomAccessFile(File file,String mode);

其中引數 mode 的值可選 "r":可讀,"w" :可寫,"rw":可讀性;

2、獲取當前檔案指標位置:int RandowAccessFile.getFilePointer();

3、改變檔案指標位置(相對位置、絕對位置):

1> 絕對位置:RandowAccessFile.seek(int index);

2> 相對位置:RandowAccessFile.skipByte(int step); 相對當前位置

4、給寫入檔案預留空間:RandowAccessFile.setLength(long len);

斷點續傳實現原理:

  1)下載斷開的時候,記錄檔案斷點的位置position;

  2)繼續下載的時候,通過RandomAccessFile找到之前的position位置開始下載

實際操作:

  我們在D盤的根目錄下建立一個名為”test.txt”的檔案,檔案內容很簡單,如圖所示:

Java檔案斷點續傳實現原理解析

沒錯,我們輸入的內容就是簡單的6個英語字母。然後我們右鍵→屬性:

Java檔案斷點續傳實現原理解析

  我們要實現的效果很簡單:將在D盤的”test.txt”檔案寫入到E盤當中,但中途我們會模擬一次”中斷”行為,然後在重新繼續上傳,最終完成整個過程。

  也就是說,我們這裡將會把“D盤”視作一臺電腦,並且直接將”E盤”視作一臺伺服器。那麼這樣我們甚至都不再與http協議扯上半毛錢關係了,(當然實際開發我們肯定是還是得與它扯上關係的 ^<^),從而只關心最基本的檔案讀寫的”斷”和”續”的原理是怎麼樣的。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;

public class Test {
  private static int position = -1;

  public static void main(String[] args) {
    // 原始檔與目標檔案
    File sourceFile = new File("D:/","test.txt");
    File targetFile = new File("E:/","test.txt");
    // 輸入輸出流
    FileInputStream fis = null;
    FileOutputStream fos = null;
    // 資料緩衝區
    byte[] buf = new byte[1];

    try {
      fis = new FileInputStream(sourceFile);
      fos = new FileOutputStream(targetFile);
      // 資料讀寫
      while (fis.read(buf) != -1) {
        fos.write(buf);
        // 當已經上傳了3位元組的檔案內容時,模擬網路中斷了,丟擲異常
        if (targetFile.length() == 3) {
          position = 3;
          throw new FileAccessException();
        }
      }

    } catch (FileAccessException e) {
      keepGoing(sourceFile,targetFile,position);
    } catch (FileNotFoundException e) {
      System.out.println("指定檔案不存在");
    } catch (IOException e) {

    } finally {
      try {
        // 關閉輸入輸出流
        if (fis != null)
          fis.close();

        if (fos != null)
          fos.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  private static void keepGoing(File source,File target,int position) {
    try {
      Thread.sleep(10000);
    } catch (Exception e) {
      e.printStackTrace();
    }

    try {
      RandomAccessFile readFile = new RandomAccessFile(source,"rw");
      RandomAccessFile writeFile = new RandomAccessFile(target,"rw");

      readFile.seek(position);
      writeFile.seek(position);

      // 資料緩衝區
      byte[] buf = new byte[1];
      // 資料讀寫
      while (readFile.read(buf) != -1) {
        writeFile.write(buf);
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}

class FileAccessException extends Exception {
}

總結一下,我們在這次改動當中都做了什麼工作:

  • 首先,我們定義了一個變數position,記錄在發生中斷的時候,已完成讀寫的位置。(這是為了方便,實際來說肯定應該講這個值存到檔案或者資料庫等進行持久化)
  • 然後在檔案讀寫的while迴圈中,我們去模擬一箇中斷行為的發生。這裡是當targetFile的檔案長度為3個位元組則模擬丟擲一個我們自定義的異常。(我們可以想象為實際下載中,已經上傳(下載)了”x”個位元組的內容,這個時候網路中斷了,那麼我們就在網路中斷丟擲的異常中將”x”記錄下來)。
  • 剩下的就如果我們之前說的一樣,在“續傳”行為開始後,通過RandomAccessFile類來包裝我們的檔案,然後通過seek將指標指定到之前發生中斷的位置進行讀寫就搞定了。(實際的檔案下載上傳,我們當然需要將儲存的中斷值上傳給伺服器,這個方式通常為httpConnection.setRequestProperty(“RANGE”,”bytes=x”);)

在我們這段程式碼,開啟”續傳“行為,即keepGoing方法中:我們起頭讓執行緒休眠10秒鐘,這正是為了讓我們執行程式看到效果。
現在我們執行程式,那麼檔案就會開啟“由D盤上傳到E盤的過程”,我們首先點開E盤,會發現的確多了一個test.txt檔案,開啟它發現內容如下:

Java檔案斷點續傳實現原理解析

沒錯,這個時候我們發現內容只有“abc”。這是在我們預料以內的,因為我們的程式模擬在檔案上傳了3個位元組的時候發生了中斷。

Ok,我們靜靜的等待10秒鐘過去,然後再點開該檔案,看看是否能夠成功:

Java檔案斷點續傳實現原理解析

通過截圖我們發現內容的確已經變成了“abc”,由此也就完成了續傳。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。