Java IO詳解(七)------隨機訪問文件流


File 類的介紹:http://www.cnblogs.com/ysocean/p/6851878.html

Java IO 流的分類介紹:http://www.cnblogs.com/ysocean/p/6854098.html

Java IO 字節輸入輸出流:http://www.cnblogs.com/ysocean/p/6854541.html

Java IO 字符輸入輸出流:https://i.cnblogs.com/EditPosts.aspx?postid=6859242

Java IO 包裝流:http://www.cnblogs.com/ysocean/p/6864080.html

Java IO 對象流(序列化與反序列化):http://www.cnblogs.com/ysocean/p/6870069.html

 

1、什么是 隨機訪問文件流 RandomAccessFile?

  該類的實例支持讀取和寫入隨機訪問文件。 隨機訪問文件的行為類似於存儲在文件系統中的大量字節。 有一種游標,或索引到隱含的數組,稱為文件指針 ; 輸入操作讀取從文件指針開始的字節,並使文件指針超過讀取的字節。 如果在讀/寫模式下創建隨機訪問文件,則輸出操作也可用; 輸出操作從文件指針開始寫入字節,並將文件指針提前到寫入的字節。 寫入隱式數組的當前端的輸出操作會導致擴展數組。 文件指針可以通過讀取getFilePointer方法和由設置seek方法。

  通俗來講:我們以前講的 IO 字節流,包裝流等都是按照文件內容的順序來讀取和寫入的。而這個隨機訪問文件流我們可以再文件的任意地方寫入數據,也可以讀取任意地方的字節。

 

我們查看 底層源碼,可以看到:

public class RandomAccessFile implements DataOutput, DataInput, Closeable {

  實現了 DataOutput類,DataInput類,那么這兩個類是什么呢?

 

2、數據流:DataOutput,DataInput

  ①、DataOutput:提供將數據從任何Java基本類型轉換為一系列字節,並將這些字節寫入二進制流。 還有一種將String轉換為modified UTF-8格式(這種格式會在寫入的數據之前默認增加兩個字節的長度)並編寫結果字節系列的功能。

  ②、DataInput:提供從二進制流讀取字節並從其中重建任何Java原語類型的數據。 還有,為了重建設施String從數據modified UTF-8格式。 

下面我們以其典型實現:DataOutputSteam、DataInputStream 來看看它的用法:

//數據輸出流
		File file = new File("io"+File.separator+"a.txt");
		DataOutputStream dop = new DataOutputStream(new FileOutputStream(file));
		//寫入三種類型的數據
		dop.write(65);
		dop.writeChar('哥');
		dop.writeUTF("帥鍋");
		dop.close();
		
		//數據輸入流
		DataInputStream dis = new DataInputStream(new FileInputStream(file));
		System.out.println(dis.read());  //65
		System.out.println(dis.readChar());	//哥
		System.out.println(dis.readUTF());	//帥鍋
		dis.close();

  

 

3、通過上面的例子,我們可以看到因為 RandomAccessFile 實現了數據輸入輸出流,那么 RandomAccessFile 這一個類就可以完成 輸入輸出的功能了。

  

這里面第二個參數:String mode 有以下幾種形式:(ps:為什么這里的值是固定的而不弄成枚舉形式,不然很容易寫錯,這是因為隨機訪問流出現在枚舉類型之前,屬於Java 歷史遺留問題)

  

 

 第一種:用 隨機流順序讀取數據

public class RandomAccessFileTest {
	public static void main(String[] args) throws Exception {
		File file = new File("io"+File.separator+"a.txt");
		write(file);
		read(file);
	}
	
	/**
	 * 隨機流讀數據
	 */
	private static void read(File file) throws Exception {
		//以 r 即只讀的方法讀取數據
		RandomAccessFile ras = new RandomAccessFile(file, "r");
		byte b = ras.readByte();
		System.out.println(b); //65
		
		int i = ras.readInt();
		System.out.println(i); //97
		
		String str = ras.readUTF(); //帥鍋
		System.out.println(str);
		ras.close();
	}

	/**
	 * 隨機流寫數據
	 */
	private static void write(File file) throws Exception{
		//以 rw 即讀寫的方式寫入數據
		RandomAccessFile ras = new RandomAccessFile(file, "rw");
		ras.writeByte(65);
		ras.writeInt(97);
		ras.writeUTF("帥鍋");
		
		ras.close();
	}

}

  

第二種:隨機讀取,那么我們先介紹這兩個方法

這里所說的偏移量,也就是字節數。一個文件是有N個字節數組成,那么我們可以通過設置讀取或者寫入的偏移量,來達到隨機讀取或寫入的目的。

我們先看看Java 各數據類型所占字節數:

下面是 隨機讀取數據例子:

/**
	 * 隨機流讀數據
	 */
	private static void read(File file) throws Exception {
		//以 r 即只讀的方法讀取數據
		RandomAccessFile ras = new RandomAccessFile(file, "r");
		
		byte b = ras.readByte();
		System.out.println(b); //65
		//我們已經讀取了一個字節的數據,那么當前偏移量為 1
		System.out.println(ras.getFilePointer());  //1 
		//這時候我們設置 偏移量為 5,那么可以直接讀取后面的字符串(前面是一個字節+一個整型數據=5個字節)
		ras.seek(5);
		String str = ras.readUTF(); //帥鍋
		System.out.println(str);
		
		//這時我們設置 偏移量為 0,那么從頭開始
		ras.seek(0);
		System.out.println(ras.readByte()); //65
		
		//需要注意的是:UTF 寫入的數據默認會在前面增加兩個字節的長度
		
		ras.close();
	}

  

 隨機流復制文件:

/**
	 * 隨機流復制文件
	 * @param fileA
	 * @param B
	 * @throws Exception 
	 */
	private static void copyFile(File fileA,File fileB) throws Exception{
		
		RandomAccessFile srcRA = new RandomAccessFile(fileA, "rw");
		RandomAccessFile descRA = new RandomAccessFile(fileB, "rw");
		
		//向 文件 a.txt 中寫入數據
		srcRA.writeByte(65);
		srcRA.writeInt(97);
		srcRA.writeUTF("帥鍋");
		//獲取 a.txt 文件的字節長度
		int len = (int) srcRA.length();
		srcRA.seek(0);
		System.out.println(srcRA.readByte()+srcRA.readInt()+srcRA.readUTF());
		
		//開始復制
		srcRA.seek(0);
		//定義一個數組,用來存放 a.txt 文件的數據
		byte[] buffer = new byte[len];
		//將 a.txt 文件的內容讀到 buffer 中
		srcRA.readFully(buffer);
		//再將 buffer 寫入到 b.txt文件中
		descRA.write(buffer);
		
		//讀取 b.txt 文件中的數據
		descRA.seek(0);
		System.out.println(descRA.readByte()+descRA.readInt()+descRA.readUTF());
		//關閉流資源
		srcRA.close();
		descRA.close();
	}

  

ps:一般多線程下載、斷點下載都可以運用此隨機流

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM