天天看點

Java對檔案的讀、寫随機通路,RandomAccessFile類的使用分析

  在網上看了一些關于java中的RandomAccessFile類的介紹,又經過檢視Java API和自己編的測試程式,總算是對RandomAccessFile的使用有了一定的了解。自己做了以下比較詳細的總結吧。

  1.RandomAccessFile類的簡單介紹

  該類的執行個體支援對檔案的随機讀取和寫入。随機存取檔案的行為類似存儲在檔案系統中的一個大型位元組數組。存在指向該隐含數組的光标或索引,稱為檔案指針。讀取操作從檔案指針開始讀取位元組,并随着對位元組的讀取而前移此檔案指針。如果随機存取檔案以讀取/寫入模式建立,則寫入操作也可用;寫入操作從檔案指針開始寫入位元組,并随着對位元組的寫入而前移此檔案指針。該檔案指針可以通過 <code>getFilePointer</code> 方法讀取,并通過 <code>seek</code> 方法設定。

  通常,如果此類中的所有讀取例程在讀取所需數量的位元組之前已到達檔案末尾,則抛出 <code>EOFException。</code>如果由于某些原因無法讀取任何位元組,而不是在讀取所需數量的位元組之前已到達檔案末尾,則抛出 <code>IOException</code>。需要特别指出的是,如果流已被關閉,則可能抛出 <code>IOException</code>。

  2.一個檔案讀取錯誤例子引出的思考

  執行輸出: 檔案長度為:4

        讀出的資料位:825373492

  分析:這是因為RandomAccessFile類的執行個體都是根據要讀取的資料類型來讀取指定大小的資料塊到變量。int類型占4個位元組,是以readInt()函數會從檔案開頭讀取四個位元組,每個位元組都當做ASCII碼。讀到的四個ASCII碼位元組是‘1’,‘2’,‘3’,‘4’,對應十六進制為31H,32H,33H,34H,即31323334H=825373492D。

  3.随機讀寫檔案的存儲圖示

    3.1資料存放

    (1)用RandomAccessFile類寫入的資料一般都是按照ASCII字元的形式儲存在檔案中的,即以位元組的形式,位元組是計算機儲存設備編址的最小單元。

      (2)Java中各資料類型所占的位元組數,如圖表所示:  

Java對檔案的讀、寫随機通路,RandomAccessFile類的使用分析

     (3)如下圖就是依次寫入int,byte,double,int,byte,short,short資料時,在檔案中的存放。檔案指針會随着資料的寫入按照寫入後移。

Java對檔案的讀、寫随機通路,RandomAccessFile類的使用分析

    3.2資料讀取

    (1)如用readInt()方法讀取一個int資料。檔案指針會從目前位置向後讀取去四個位元組的資料,将取到的資料在強制轉換為int類型傳回即可,同時檔案指針也自動的向後移動了相應的四個位置。

      (2)如果先用readByte()方法讀取一個byte資料,讀取後檔案指針移動了一個位置(還在int原本的四個位元組中),這樣再用readInt()方法讀取一個int資料就會出現亂碼。

    (3)也就是說用RandomAccessFile類來操作檔案,應該知道資料事先是如何存放的,之後用相應的讀取就能順序的讀出,而不會出現亂碼。

   4.特殊的資料讀取

    4.1字元串讀readUTF()<code>和字元串寫writeUTF(String str)</code>

    這2個方法都帶有“UTF”,是因為寫入資料時按照utf-8編碼寫入,讀取時也是utf-8。

    每次寫入的字元串的長度是不一定的。因為Java API給出了讀取與寫入字元串是成對的,是以需要标記每次寫入的字元串的長度。每次寫入字元串時,會配置設定2個位元組來儲存,要寫入的字元串的大小,也就是一次寫入字元串的大小應該不能大于65536個位元組。每次讀取的字元串時,先從檔案指針的位置開始讀取2個位元組,分析得到要讀取字元串的長度,之後在進行讀取。如下圖所示:

      

Java對檔案的讀、寫随機通路,RandomAccessFile類的使用分析

    程式舉例:寫入2次字元串。

    檢視生成檔案:

Java對檔案的讀、寫随機通路,RandomAccessFile類的使用分析

,可以看到在漢字的前面有一些字元,其實就是2個位元組的标記字元串長度的ASCII編碼。

    4.2讀取一行<code>readLine()</code>

     (1)Java API中隻有讀取一行readLine()方法,然而沒有寫入一行writeLine()的方法。

     (2)在Windows下的行結束符号是“\r\n”。執行readLine()方法,從目前的檔案指針開始讀取,直到遇到“\r\n”或者檔案結束為止。

     (3)此方法不支援完整的 Unicode 字元集。是以用writeUTF(String str)寫入的中文需要相應的readUTF()讀取,以免出現亂碼。漢字的UTF-8編碼占3個位元組,而GBK占用2個位元組,漢字的Unicode編碼占2位元組。

     (4)在寫檔案時,為了可以更換使用<code>readLine()</code>,需要自己寫入行結束符号是“\r\n”。

    程式舉例:寫入2次字元串,以行結束符号隔開。

    程式輸出:Hello world!!!

  5.總結

  (1)RandomAccessFile類可以進行檔案的随機讀寫,就好比對一個大型的數組的操作,對于大檔案來說速度是比較慢的。

  (2)RandomAccessFile類的執行個體是根據給定的資料類型大小寫入和讀取資料,是以用writeXXX()寫入的資料,最好用相應的readXXX()來讀取。

  (3)RandomAccessFile類的執行個體寫入也是按照位元組順序的寫入,生成檔案的。要讀取這樣的檔案就必須知道是如何生成的,否則很可能出現讀取出亂碼。

參考:

1.Java API文檔