1. 程式人生 > 其它 >io流之--RandomAccessFile簡介和使用

io流之--RandomAccessFile簡介和使用

本篇文章主要介紹RandomAccessFile,該類是IO流體系中功能最豐富的檔案內容訪問類,既可以讀取檔案內容,也可以向檔案輸出資料。

一、RandomAccessFile簡介

RandomAccessFile既可以讀取檔案內容,也可以向檔案輸出資料。同時,RandomAccessFile支援“隨機訪問”的方式,程式快可以直接跳轉到檔案的任意地方來讀寫資料。

由於RandomAccessFile可以自由訪問檔案的任意位置,所以如果需要訪問檔案的部分內容,而不是把檔案從頭讀到尾,使用RandomAccessFile將是更好的選擇。

與OutputStream、Writer等輸出流不同的是,RandomAccessFile允許自由定義檔案記錄指標,RandomAccessFile可以不從開始的地方開始輸出,因此RandomAccessFile可以向已存在的檔案後追加內容。如果程式需要向已存在的檔案後追加內容,則應該使用RandomAccessFile。

RandomAccessFile的方法雖然多,但它有一個最大的侷限,就是隻能讀寫檔案,不能讀寫其他IO節點。

RandomAccessFile的一個重要使用場景就是網路請求中的多執行緒下載及斷點續傳。

二、RandomAccessFile中的方法

1.RandomAccessFile的建構函式

RandomAccessFile類有兩個建構函式,其實這兩個建構函式基本相同,只不過是指定檔案的形式不同——一個需要使用String引數來指定檔名,一個使用File引數來指定檔案本身。除此之外,建立RandomAccessFile物件時還需要指定一個mode引數,該引數指定RandomAccessFile的訪問模式,一共有4種模式。

**"r" : ** 以只讀方式開啟。呼叫結果物件的任何 write 方法都將導致丟擲 IOException。
"rw": 開啟以便讀取和寫入。
"rws": 開啟以便讀取和寫入。相對於 "rw","rws" 還要求對“檔案的內容”或“元資料”的每個更新都同步寫入到基礎儲存裝置。
"rwd" : 開啟以便讀取和寫入,相對於 "rw","rwd" 還要求對“檔案的內容”的每個更新都同步寫入到基礎儲存裝置。

2.RandomAccessFile的重要方法

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

RandomAccessFile物件包含了一個記錄指標,用以標識當前讀寫處的位置,當程式新建立一個RandomAccessFile物件時,該物件的檔案指標記錄位於檔案頭(也就是0處),當讀/寫了n個位元組後,檔案記錄指標將會後移n個位元組。除此之外,RandomAccessFile還可以自由移動該記錄指標。下面就是RandomAccessFile具有的兩個特殊方法,來操作記錄指標,實現隨機訪問:

long getFilePointer( ):返回檔案記錄指標的當前位置
void seek(long pos ):將檔案指標定位到pos位置

三、RandomAccessFile的使用

利用RandomAccessFile實現檔案的多執行緒下載,即多執行緒下載一個檔案時,將檔案分成幾塊,每塊用不同的執行緒進行下載。下面是一個利用多執行緒在寫檔案時的例子,其中預先分配檔案所需要的空間,然後在所分配的空間中進行分塊,然後寫入:

/** 
 * 測試利用多執行緒進行檔案的寫操作 
 */  
public class Test {  
  
    public static void main(String[] args) throws Exception {  
        // 預分配檔案所佔的磁碟空間,磁碟中會建立一個指定大小的檔案  
        RandomAccessFile raf = new RandomAccessFile("D://abc.txt", "rw");  
        raf.setLength(1024*1024); // 預分配 1M 的檔案空間  
        raf.close();  
          
        // 所要寫入的檔案內容  
        String s1 = "第一個字串";  
        String s2 = "第二個字串";  
        String s3 = "第三個字串";  
        String s4 = "第四個字串";  
        String s5 = "第五個字串";  
          
        // 利用多執行緒同時寫入一個檔案  
        new FileWriteThread(1024*1,s1.getBytes()).start(); // 從檔案的1024位元組之後開始寫入資料  
        new FileWriteThread(1024*2,s2.getBytes()).start(); // 從檔案的2048位元組之後開始寫入資料  
        new FileWriteThread(1024*3,s3.getBytes()).start(); // 從檔案的3072位元組之後開始寫入資料  
        new FileWriteThread(1024*4,s4.getBytes()).start(); // 從檔案的4096位元組之後開始寫入資料  
        new FileWriteThread(1024*5,s5.getBytes()).start(); // 從檔案的5120位元組之後開始寫入資料  
    }  
      
    // 利用執行緒在檔案的指定位置寫入指定資料  
    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) {  
                }  
            }  
        }  
    }  
  
}  

當RandomAccessFile向指定檔案中插入內容時,將會覆蓋掉原有內容。如果不想覆蓋掉,則需要將原有內容先讀取出來,然後先把插入內容插入後再把原有內容追加到插入內容後。

艾歐尼亞,昂揚不滅,為了更美好的明天而戰(#^.^#)