歡迎您光臨本站 註冊首頁

Java文件斷點續傳實現原理解析

←手機掃碼閱讀     limiyoyo @ 2020-06-09 , reply:0

一、作用:

隨機流(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”的文件,文件內容很簡單,如圖所示:

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

  我們要實現的效果很簡單:將在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文件,打開它發現內容如下:

沒錯,這個時候我們發現內容只有“abc”。這是在我們預料以內的,因為我們的程序模擬在文件上傳了3個字節的時候發生了中斷。

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

 

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

                                                       

   


[limiyoyo ] Java文件斷點續傳實現原理解析已經有224次圍觀

http://coctec.com/docs/java/show-post-237604.html