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:一般多線程下載、斷點下載都可以運用此隨機流
