RandomAccessFile是java Io體系中功能最豐富的文件內容訪問類。便可以讀取文件內容,也能夠向文件中寫入內容。可是和其餘輸入/輸入流不一樣的是,程序能夠直接跳到文件的任意位置來讀寫數據。
由於RandomAccessFile能夠自由訪問文件的任意位置,因此若是咱們但願只訪問文件的部份內容,那就可使用RandomAccessFile類。
與OutputStearm,Writer等輸出流不一樣的是,RandomAccessFile類容許自由定位文件記錄指針,因此RandomAccessFile能夠不從文件開始的地方進行輸出,因此RandomAccessFile能夠向已存在的文件後追加內容。則應該使用RandomAccessFile。java
RandomAccessFile類包含了一個記錄指針,用以標識當前讀寫處的位置,當程序新建立一個RandomAccessFile對象時,該對象的文件記錄指針位於文件頭(也就是0處),當讀/寫了n個字節後,文件記錄指針將會向後移動n個字節。除此以外,RandomAccessFile能夠自由的移動記錄指針,便可以向前移動,也能夠向後移動。RandomAccessFile包含了如下兩個方法來操做文件的記錄指針.緩存
RandomAccessFile便可以讀文件,也能夠寫,因此它即包含了徹底相似於InputStream的3個read()方法,其用法和InputStream的3個read()方法徹底同樣;也包含了徹底相似於OutputStream的3個write()方法,其用法和OutputStream的3個Writer()方法徹底同樣。除此以外,RandomAccessFile還包含了一系類的readXXX()和writeXXX()方法來完成輸入和輸出。dom
RandomAccessFile有兩個構造器,其實這兩個構造器基本相同,只是指定文件的形式不一樣而已,一個使用String參數來指定文件名,一個使用File參數來指定文件自己。除此以外,建立RandomAccessFile對象還須要指定一個mode參數。該參數指定RandomAccessFile的訪問模式,有如下4個值:spa
public static void main(String[] args)throws IOException { String filePath="E:\\learnproject\\Iotest\\lib\\src\\main\\java\\com\\Test.txt"; RandomAccessFile raf=null; File file=null; try { file=new File(filePath); raf=new RandomAccessFile(file,"r"); // 獲取 RandomAccessFile對象文件指針的位置,初始位置爲0 System.out.print("輸入內容:"+raf.getFilePointer()); //移動文件記錄指針的位置 raf.seek(1000); byte[] b=new byte[1024]; int hasRead=0; //循環讀取文件 while((hasRead=raf.read(b))>0){ //輸出文件讀取的內容 System.out.print(new String(b,0,hasRead)); } }catch (IOException e){ e.printStackTrace(); }finally { raf.close(); } }
在上面的程序的關鍵代碼兩處,一處是建立了RandomAccessFile對象,該對象以只讀模式打開了Test.txt文件,這意味着RandomAccessFile文件只能讀取文件內容,不能執行寫入。第二處調用了seek(1000)方法,是指把文件的記錄指針定位到1000字節的位置。也就是說程序將從1000字節開始讀取數據。其餘部分的代碼的讀取方式和其餘的輸入流沒有區別。指針
public class RandomAccessFileTest2 { public static void main(String[] args)throws IOException { String filePath="E:\\learnproject\\Iotest\\lib\\src\\main\\java\\com\\Test.txt"; RandomAccessFile raf=null; File file=null; try { file=new File(filePath); // 以讀寫的方式打開一個RandomAccessFile對象 raf=new RandomAccessFile(file,"rw"); //將記錄指針移動到該文件的最後 raf.seek(raf.length()); //向文件末尾追加內容 raf.writeChars("這是追加內容。。"); }catch (IOException e){ e.printStackTrace(); }finally { raf.close(); } }
上面代碼先以讀,寫方式建立了一個RandomAccessFile對象,而後將文件記錄指針移動到最後,接下來使用RandomAccessFile向文件中寫入內容。和其餘輸出例OutputStream的方式相同。每運行一次上面的程序,就能發現text.txt文件中多添加了一行內容。code
注:RandomAccessFile不能向文件的指定位置插入內容,若是直接將文件記錄指針移動到中間某位置後開始輸出,則新輸出的內容會覆蓋文件原有的內容,若是須要向指定位置插入內容,程序須要先把插入點後面的內容寫入緩存區,等把須要插入的數據寫入到文件後,再將緩存區的內容追加到文件後面。對象
/** * 插入文件指定位置的指定內容 * @param filePath 文件路徑 * @param pos 插入文件的指定位置 * @param insertContent 插入文件中的內容 * @throws IOException */ public static void insert(String filePath,long pos,String insertContent)throws IOException{ RandomAccessFile raf=null; File tmp=File.createTempFile("tmp",null); tmp.deleteOnExit(); try { // 以讀寫的方式打開一個RandomAccessFile對象 raf = new RandomAccessFile(new File(filePath), "rw"); //建立一個臨時文件來保存插入點後的數據 FileOutputStream fileOutputStream = new FileOutputStream(tmp); FileInputStream fileInputStream = new FileInputStream(tmp); //把文件記錄指針定位到pos位置 raf.seek(pos); raf.seek(pos); //------下面代碼將插入點後的內容讀入臨時文件中保存----- byte[] bbuf = new byte[64]; //用於保存實際讀取的字節數據 int hasRead = 0; //使用循環讀取插入點後的數據 while ((hasRead = raf.read(bbuf)) != -1) { //將讀取的內容寫入臨時文件 fileOutputStream.write(bbuf, 0, hasRead); } //-----下面代碼用於插入內容 ----- //把文件記錄指針從新定位到pos位置 raf.seek(pos); //追加須要插入的內容 raf.write(insertContent.getBytes()); //追加臨時文件中的內容 while ((hasRead = fileInputStream.read(bbuf)) != -1) { //將讀取的內容寫入臨時文件 raf.write(bbuf, 0, hasRead); } }catch (Exception e){ throw e; } } public static void main(String[] args)throws IOException { String filePath="E:\\learnproject\\Iotest\\lib\\src\\main\\java\\com\\Test.txt"; insert(filePath,1000,"插入指定位置指定內容"); }
上面的程序使用File類的createTempFile方法建立了一個臨時文件(該文件將在JVM退出後被刪除),用於保存被插入點後面的內容。程序先將文件中插入點後的內容讀入臨時文件中,而後從新定位到插入點,將須要插入的內容添加到文件後面,最後將臨時文件的內容添加到文件後面,經過這個過程就能夠向指定文件,指定位置插入內容。每次運行上面的程序,都會看到Test.txt文件中多了一行內容。blog