RandomAccessFile亂碼問題

轉自:http://www.cnblogs.com/xudong-bupt/archive/2013/04/20/3028980.html     Thankshtml

Java對文件的讀、寫隨機訪問,RandomAccessFile類的使用分析java

  在網上看了一些關於java中的RandomAccessFile類的介紹,又通過查看Java API和本身編的測試程序,總算是對RandomAccessFile的使用有了必定的瞭解。本身作了如下比較詳細的總結吧。數組

  1.RandomAccessFile類的簡單介紹dom

  該類的實例支持對文件的隨機讀取和寫入。隨機存取文件的行爲相似存儲在文件系統中的一個大型字節數組。存在指向該隱含數組的光標或索引,稱爲文件指針。讀取操做從文件指針開始讀取字節,並隨着對字節的讀取而前移此文件指針。若是隨機存取文件以讀取/寫入模式建立,則寫入操做也可用;寫入操做從文件指針開始寫入字節,並隨着對字節的寫入而前移此文件指針。該文件指針能夠經過 getFilePointer 方法讀取,並經過 seek 方法設置。函數

  一般,若是此類中的全部讀取例程在讀取所需數量的字節以前已到達文件末尾,則拋出 EOFException若是因爲某些緣由沒法讀取任何字節,而不是在讀取所需數量的字節以前已到達文件末尾,則拋出 IOException。須要特別指出的是,若是流已被關閉,則可能拋出 IOExceptionpost

  2.一個文件讀取錯誤例子引出的思考測試

複製代碼
import java.io.RandomAccessFile; public class RandomAccessFile_test { public static void main(String args[]) throws Exception{ RandomAccessFile access=new RandomAccessFile("c:\\a.txt","rw"); //文件a.txt中只有一個整數1234 System.out.println("文件長度爲:"+access.length()); System.out.println("讀出的數據位:"+access.readInt()); access.close(); } }
複製代碼

  執行輸出: 文件長度爲:4         讀出的數據位:825373492this

  分析:這是由於RandomAccessFile類的實例都是根據要讀取的數據類型來讀取指定大小的數據塊到變量。int類型佔4個字節,所以readInt()函數會從文件開頭讀取四個字節,每一個字節都當作ASCII碼。讀到的四個ASCII碼字節是‘1’,‘2’,‘3’,‘4’,對應十六進制爲31H,32H,33H,34H,即31323334H=825373492D。編碼

  3.隨機讀寫文件的存儲圖示url

    3.1數據存放

    (1)用RandomAccessFile類寫入的數據通常都是按照ASCII字符的形式保存在文件中的,即以字節的形式,字節是計算機存儲設備編址的最小單元。

      (2)Java中各數據類型所佔的字節數,如圖表所示:  

     (3)以下圖就是依次寫入int,byte,double,int,byte,short,short數據時,在文件中的存放。文件指針會隨着數據的寫入按照寫入後移。

    3.2數據讀取

    (1)如用readInt()方法讀取一個int數據。文件指針會從當前位置向後讀取去四個字節的數據,將取到的數據在強制轉換爲int類型返回便可,同時文件指針也自動的向後移動了相應的四個位置。

      (2)若是先用readByte()方法讀取一個byte數據,讀取後文件指針移動了一個位置(還在int本來的四個字節中),這樣再用readInt()方法讀取一個int數據就會出現亂碼。

    (3)也就是說用RandomAccessFile類來操做文件,應該知道數據事先是如何存放的,以後用相應的讀取就能順序的讀出,而不會出現亂碼。

   4.特殊的數據讀取

    4.1字符串讀readUTF()和字符串寫writeUTF(String str)

    這2個方法都帶有「UTF」,是由於寫入數據時按照utf-8編碼寫入,讀取時也是utf-8。

    每次寫入的字符串的長度是不必定的。由於Java API給出了讀取與寫入字符串是成對的,所以須要標記每次寫入的字符串的長度。每次寫入字符串時,會分配2個字節來保存,要寫入的字符串的大小,也就是一次寫入字符串的大小應該不能大於65536個字節。每次讀取的字符串時,先從文件指針的位置開始讀取2個字節,分析獲得要讀取字符串的長度,以後在進行讀取。以下圖所示:

      

    程序舉例:寫入2次字符串。

複製代碼
import java.io.RandomAccessFile; public class Char_Byte{ public static void main(String args[]) throws Exception{ RandomAccessFile access=new RandomAccessFile("C:\\a.txt","rw"); //「讀寫」方式創建類的實例 access.writeUTF("你好"); //以utf-8格式寫入數據 access.writeUTF("朋友"); //以utf-8格式寫入數據  access.close(); } }
複製代碼

    查看生成文件,能夠看到在漢字的前面有一些字符,其實就是2個字節的標記字符串長度的ASCII編碼。

    4.2讀取一行readLine()

     (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)在寫文件時,爲了能夠更換使用readLine(),須要本身寫入行結束符號是「\r\n」。     程序舉例:寫入2次字符串,以行結束符號隔開。

複製代碼
import java.io.RandomAccessFile; public class Char_Byte{ public static void main(String args[]) throws Exception{ RandomAccessFile access=new RandomAccessFile("C:\\a.txt","rw"); //「讀寫」方式創建類的實例 access.writeBytes("Hello world!!!"); //寫入數據 access.writeBytes("\r\n");//寫入行結束符號 access.writeUTF("he he"); //以utf-8格式寫入數據  access.close(); access=new RandomAccessFile("C:\\a.txt","rw"); String context=access.readLine(); //讀取數據  access.close(); System.out.println(context); } }
複製代碼

    程序輸出:Hello world!!!

  5.總結

  (1)RandomAccessFile類能夠進行文件的隨機讀寫,就比如對一個大型的數組的操做,對於大文件來講速度是比較慢的。

  (2)RandomAccessFile類的實例是根據給定的數據類型大小寫入和讀取數據,所以用writeXXX()寫入的數據,最好用相應的readXXX()來讀取。

  (3)RandomAccessFile類的實例寫入也是按照字節順序的寫入,生成文件的。要讀取這樣的文件就必須知道是如何生成的,不然極可能出現讀取出亂碼。

參考:

1.Java API文檔

2.http://blog.csdn.net/akon_vm/article/details/7429245

3.http://zhidao.baidu.com/question/139267246.html

相關文章
相關標籤/搜索