Java IO流詳解(三)——RandomAccessFile

本篇文章主要介紹RandomAccessFile,該類是IO流體系中功能最豐富的文件內(nèi)容訪問類,既可以讀取文件內(nèi)容,也可以向文件輸出數(shù)據(jù)。

一、RandomAccessFile簡介

RandomAccessFile既可以讀取文件內(nèi)容,也可以向文件輸出數(shù)據(jù)。同時(shí),RandomAccessFile支持“隨機(jī)訪問”的方式,程序快可以直接跳轉(zhuǎn)到文件的任意地方來讀寫數(shù)據(jù)。

由于RandomAccessFile可以自由訪問文件的任意位置,所以如果需要訪問文件的部分內(nèi)容,而不是把文件從頭讀到尾,使用RandomAccessFile將是更好的選擇。

與OutputStream、Writer等輸出流不同的是,RandomAccessFile允許自由定義文件記錄指針,RandomAccessFile可以不從開始的地方開始輸出,因此RandomAccessFile可以向已存在的文件后追加內(nèi)容。如果程序需要向已存在的文件后追加內(nèi)容,則應(yīng)該使用RandomAccessFile。

RandomAccessFile的方法雖然多,但它有一個最大的局限,就是只能讀寫文件,不能讀寫其他IO節(jié)點(diǎn)。

RandomAccessFile的一個重要使用場景就是網(wǎng)絡(luò)請求中的多線程下載及斷點(diǎn)續(xù)傳。

二、RandomAccessFile中的方法

1.RandomAccessFile的構(gòu)造函數(shù)

RandomAccessFile類有兩個構(gòu)造函數(shù),其實(shí)這兩個構(gòu)造函數(shù)基本相同,只不過是指定文件的形式不同——一個需要使用String參數(shù)來指定文件名,一個使用File參數(shù)來指定文件本身。除此之外,創(chuàng)建RandomAccessFile對象時(shí)還需要指定一個mode參數(shù),該參數(shù)指定RandomAccessFile的訪問模式,一共有4種模式。

**"r" : ** 以只讀方式打開。調(diào)用結(jié)果對象的任何 write 方法都將導(dǎo)致拋出 IOException。
"rw": 打開以便讀取和寫入。
"rws": 打開以便讀取和寫入。相對于 "rw","rws" 還要求對“文件的內(nèi)容”或“元數(shù)據(jù)”的每個更新都同步寫入到基礎(chǔ)存儲設(shè)備。
"rwd" : 打開以便讀取和寫入,相對于 "rw","rwd" 還要求對“文件的內(nèi)容”的每個更新都同步寫入到基礎(chǔ)存儲設(shè)備。

2.RandomAccessFile的重要方法

RandomAccessFile既可以讀文件,也可以寫文件,所以類似于InputStream的read()方法,以及類似于OutputStream的write()方法,RandomAccessFile都具備。除此之外,RandomAccessFile具備兩個特有的方法,來支持其隨機(jī)訪問的特性。

RandomAccessFile對象包含了一個記錄指針,用以標(biāo)識當(dāng)前讀寫處的位置,當(dāng)程序新創(chuàng)建一個RandomAccessFile對象時(shí),該對象的文件指針記錄位于文件頭(也就是0處),當(dāng)讀/寫了n個字節(jié)后,文件記錄指針將會后移n個字節(jié)。除此之外,RandomAccessFile還可以自由移動該記錄指針。下面就是RandomAccessFile具有的兩個特殊方法,來操作記錄指針,實(shí)現(xiàn)隨機(jī)訪問:

long getFilePointer( ):返回文件記錄指針的當(dāng)前位置
void seek(long pos ):將文件指針定位到pos位置

三、RandomAccessFile的使用

利用RandomAccessFile實(shí)現(xiàn)文件的多線程下載,即多線程下載一個文件時(shí),將文件分成幾塊,每塊用不同的線程進(jìn)行下載。下面是一個利用多線程在寫文件時(shí)的例子,其中預(yù)先分配文件所需要的空間,然后在所分配的空間中進(jìn)行分塊,然后寫入:

/** 
 * 測試?yán)枚嗑€程進(jìn)行文件的寫操作 
 */  
public class Test {  
  
    public static void main(String[] args) throws Exception {  
        // 預(yù)分配文件所占的磁盤空間,磁盤中會創(chuàng)建一個指定大小的文件  
        RandomAccessFile raf = new RandomAccessFile("D://abc.txt", "rw");  
        raf.setLength(1024*1024); // 預(yù)分配 1M 的文件空間  
        raf.close();  
          
        // 所要寫入的文件內(nèi)容  
        String s1 = "第一個字符串";  
        String s2 = "第二個字符串";  
        String s3 = "第三個字符串";  
        String s4 = "第四個字符串";  
        String s5 = "第五個字符串";  
          
        // 利用多線程同時(shí)寫入一個文件  
        new FileWriteThread(1024*1,s1.getBytes()).start(); // 從文件的1024字節(jié)之后開始寫入數(shù)據(jù)  
        new FileWriteThread(1024*2,s2.getBytes()).start(); // 從文件的2048字節(jié)之后開始寫入數(shù)據(jù)  
        new FileWriteThread(1024*3,s3.getBytes()).start(); // 從文件的3072字節(jié)之后開始寫入數(shù)據(jù)  
        new FileWriteThread(1024*4,s4.getBytes()).start(); // 從文件的4096字節(jié)之后開始寫入數(shù)據(jù)  
        new FileWriteThread(1024*5,s5.getBytes()).start(); // 從文件的5120字節(jié)之后開始寫入數(shù)據(jù)  
    }  
      
    // 利用線程在文件的指定位置寫入指定數(shù)據(jù)  
    static class FileWriteThread extends Thread{  
        private int skip;  
        private byte[] content;  
          
        public FileWriteThread(int skip,byte[] content){  
            this.skip = skip;  
            this.content = content;  
        }  
          
        public void run(){  
            RandomAccessFile raf = null;  
            try {  
                raf = new RandomAccessFile("D://abc.txt", "rw");  
                raf.seek(skip);  
                raf.write(content);  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            } finally {  
                try {  
                    raf.close();  
                } catch (Exception e) {  
                }  
            }  
        }  
    }  
  
}  

當(dāng)RandomAccessFile向指定文件中插入內(nèi)容時(shí),將會覆蓋掉原有內(nèi)容。如果不想覆蓋掉,則需要將原有內(nèi)容先讀取出來,然后先把插入內(nèi)容插入后再把原有內(nèi)容追加到插入內(nèi)容后。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,341評論 11 349
  • 在經(jīng)過一次沒有準(zhǔn)備的面試后,發(fā)現(xiàn)自己雖然寫了兩年的android代碼,基礎(chǔ)知識卻忘的差不多了。這是程序員的大忌,沒...
    猿來如癡閱讀 2,866評論 3 10
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,740評論 18 399
  • 二十歲。 二十歲,好像也沒什么不同,朋友有一兩個,討厭的人有一兩個。 時(shí)光很長,記憶卻斷斷續(xù)續(xù)的。當(dāng)初...
    雕塑家閱讀 267評論 0 3
  • 大腦極度缺氧,眼前一片漆黑,來不及回想,便被帶到了同學(xué)家的車上。我和她,三年同學(xué),一年同桌,初三分班,她是年級第三...
    瀚冰閱讀 748評論 0 0