Java文件斷點(diǎn)續(xù)傳實(shí)現(xiàn)原理解析
一、作用:
隨機(jī)流(RandomAccessFile)不屬于IO流,支持對(duì)文件的讀取和寫入隨機(jī)訪問。
二、隨機(jī)訪問文件原理:
首先把隨機(jī)訪問的文件對(duì)象看作存儲(chǔ)在文件系統(tǒng)中的一個(gè)大型 byte 數(shù)組,然后通過指向該 byte 數(shù)組的光標(biāo)或索引(即:文件指針 FilePointer)在該數(shù)組任意位置讀取或?qū)懭肴我鈹?shù)據(jù)。
三、相關(guān)方法說明:
1、對(duì)象聲明:RandomAccessFile raf = newRandomAccessFile(File file, String mode);
其中參數(shù) mode 的值可選 'r':可讀,'w' :可寫,'rw':可讀性;
2、獲取當(dāng)前文件指針位置:int RandowAccessFile.getFilePointer();
3、改變文件指針位置(相對(duì)位置、絕對(duì)位置):
1> 絕對(duì)位置:RandowAccessFile.seek(int index);
2> 相對(duì)位置:RandowAccessFile.skipByte(int step); 相對(duì)當(dāng)前位置
4、給寫入文件預(yù)留空間:RandowAccessFile.setLength(long len);
斷點(diǎn)續(xù)傳實(shí)現(xiàn)原理:
1)下載斷開的時(shí)候,記錄文件斷點(diǎn)的位置position;
2)繼續(xù)下載的時(shí)候,通過RandomAccessFile找到之前的position位置開始下載
實(shí)際操作:
我們?cè)贒盤的根目錄下創(chuàng)建一個(gè)名為”test.txt”的文件,文件內(nèi)容很簡單,如圖所示:
沒錯(cuò),我們輸入的內(nèi)容就是簡單的6個(gè)英語字母。然后我們右鍵→屬性:
我們要實(shí)現(xiàn)的效果很簡單:將在D盤的”test.txt”文件寫入到E盤當(dāng)中,但中途我們會(huì)模擬一次”中斷”行為,然后在重新繼續(xù)上傳,最終完成整個(gè)過程。
也就是說,我們這里將會(huì)把“D盤”視作一臺(tái)電腦,并且直接將”E盤”視作一臺(tái)服務(wù)器。那么這樣我們甚至都不再與http協(xié)議扯上半毛錢關(guān)系了,(當(dāng)然實(shí)際開發(fā)我們肯定是還是得與它扯上關(guān)系的 ^<^),從而只關(guān)心最基本的文件讀寫的”斷”和”續(xù)”的原理是怎么樣的。
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) { // 源文件與目標(biāo)文件 File sourceFile = new File('D:/', 'test.txt'); File targetFile = new File('E:/', 'test.txt'); // 輸入輸出流 FileInputStream fis = null; FileOutputStream fos = null; // 數(shù)據(jù)緩沖區(qū) byte[] buf = new byte[1]; try { fis = new FileInputStream(sourceFile); fos = new FileOutputStream(targetFile); // 數(shù)據(jù)讀寫 while (fis.read(buf) != -1) {fos.write(buf);// 當(dāng)已經(jīng)上傳了3字節(jié)的文件內(nèi)容時(shí),模擬網(wǎng)絡(luò)中斷了,拋出異常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 {// 關(guān)閉輸入輸出流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); // 數(shù)據(jù)緩沖區(qū) byte[] buf = new byte[1]; // 數(shù)據(jù)讀寫 while (readFile.read(buf) != -1) {writeFile.write(buf); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}class FileAccessException extends Exception {}
總結(jié)一下,我們?cè)谶@次改動(dòng)當(dāng)中都做了什么工作:
首先,我們定義了一個(gè)變量position,記錄在發(fā)生中斷的時(shí)候,已完成讀寫的位置。(這是為了方便,實(shí)際來說肯定應(yīng)該講這個(gè)值存到文件或者數(shù)據(jù)庫等進(jìn)行持久化) 然后在文件讀寫的while循環(huán)中,我們?nèi)ツM一個(gè)中斷行為的發(fā)生。這里是當(dāng)targetFile的文件長度為3個(gè)字節(jié)則模擬拋出一個(gè)我們自定義的異常。(我們可以想象為實(shí)際下載中,已經(jīng)上傳(下載)了”x”個(gè)字節(jié)的內(nèi)容,這個(gè)時(shí)候網(wǎng)絡(luò)中斷了,那么我們就在網(wǎng)絡(luò)中斷拋出的異常中將”x”記錄下來)。 剩下的就如果我們之前說的一樣,在“續(xù)傳”行為開始后,通過RandomAccessFile類來包裝我們的文件,然后通過seek將指針指定到之前發(fā)生中斷的位置進(jìn)行讀寫就搞定了。(實(shí)際的文件下載上傳,我們當(dāng)然需要將保存的中斷值上傳給服務(wù)器,這個(gè)方式通常為httpConnection.setRequestProperty(“RANGE”,”bytes=x”);)在我們這段代碼,開啟”續(xù)傳“行為,即keepGoing方法中:我們起頭讓線程休眠10秒鐘,這正是為了讓我們運(yùn)行程序看到效果。 現(xiàn)在我們運(yùn)行程序,那么文件就會(huì)開啟“由D盤上傳到E盤的過程”,我們首先點(diǎn)開E盤,會(huì)發(fā)現(xiàn)的確多了一個(gè)test.txt文件,打開它發(fā)現(xiàn)內(nèi)容如下:
沒錯(cuò),這個(gè)時(shí)候我們發(fā)現(xiàn)內(nèi)容只有“abc”。這是在我們預(yù)料以內(nèi)的,因?yàn)槲覀兊某绦蚰M在文件上傳了3個(gè)字節(jié)的時(shí)候發(fā)生了中斷。
Ok,我們靜靜的等待10秒鐘過去,然后再點(diǎn)開該文件,看看是否能夠成功:
通過截圖我們發(fā)現(xiàn)內(nèi)容的確已經(jīng)變成了“abc”,由此也就完成了續(xù)傳。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. ASP.NET MVC把數(shù)據(jù)庫中枚舉項(xiàng)的數(shù)字轉(zhuǎn)換成文字2. SpringMVC+Jquery實(shí)現(xiàn)Ajax功能3. 基于javaweb+jsp實(shí)現(xiàn)企業(yè)財(cái)務(wù)記賬管理系統(tǒng)4. 博客日志摘要暨RSS技術(shù)5. 低版本IE正常運(yùn)行HTML5+CSS3網(wǎng)站的3種解決方案6. WML學(xué)習(xí)之一概述和基本規(guī)則7. Java pom.xml parent引用報(bào)錯(cuò)問題解決方案8. python 集合set中 add與update區(qū)別介紹9. CSS單標(biāo)簽實(shí)現(xiàn)復(fù)雜的棋盤布局10. Java try catch finally異常處理組合詳解
