自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

高效快捷讀寫文件之 RandomAccessFile 類解說

開發(fā) 前端
本文主要圍繞 RandomAccessFile 類的基本概念和常用方法,做了一次簡單的知識總結(jié),該類是 IO 流體系中功能最豐富的文件內(nèi)容訪問類,既可以讀取文件中任意位置的內(nèi)容,也可以向文件任意位置寫入數(shù)據(jù)。

一、摘要

RandomAccessFile 類,也被稱為隨機訪問文件類。

RandomAccessFile 可以說是 Java 體系中功能最為豐富的文件操作類,相比之前介紹的通過字節(jié)流或者字符流接口方式讀寫文件,RandomAccessFile 類可以跳轉(zhuǎn)到文件的任意位置處進行讀寫數(shù)據(jù),而無需把文件從頭讀到尾,但是該類僅限于操作文件,不能訪問其他的 IO 設(shè)備,如網(wǎng)絡(luò)、內(nèi)存映像等。

所以如果需要訪問文件的部分內(nèi)容,而不是把文件從頭讀到尾,使用 RandomAccessFile 將是更好的選擇。

實際上,雖然RandomAccessFile類具備隨機讀寫數(shù)據(jù)的功能,但是它既不是InputStream的子類,也不是OutputStream的子類,絕大部分的方法都是從零開始寫的,這可能是因為  RandomAccessFile 需要在文件里面前后移動,它的行為與其它的 I/O 類有著根本性的不同,所以相對比較獨立。

RandomAccessFile對象類中內(nèi)置了一個位置指示器,可以指向當前讀寫處的位置,當讀寫 n 個字節(jié)后,文件指示器將指向這 n 個字節(jié)后的下一個字節(jié)處。剛打開文件時,文件指示器指向文件的開頭處,當移動文件指示器到新的位置時,隨后的讀寫將從新的位置開始,這是它與其他的文件讀寫方式最大的不同。

基本上,RandomAccessFile的工作方式是,結(jié)合DataInputStream和DataOutputStream類完成數(shù)據(jù)的讀寫,再加上自己的一些方法,比如定位用的 getFilePointer方法,在文件里移動用的seek方法,以及判斷文件大小length方法、跳過多少字節(jié)數(shù)的skipBytes方法等,來完成文件的隨機訪問和讀寫操作。

具體怎么使用呢,我們一起來看看!

二、RandomAccessFile 類基本介紹

下面先來看看一個簡單的例子。

// 獲取隨機訪問文件對象
RandomAccessFile raf = new RandomAccessFile(new File("randomFileDemo.txt"), "rw");
for (int i = 0; i < 10; i++) {
    // 寫入數(shù)據(jù),1個int占4個字節(jié)
    raf.writeInt(i);
}
raf.close();

System.out.println("================修改前的內(nèi)容===============" );
// 重新獲取隨機訪問文件對象
raf = new RandomAccessFile(new File("randomFileDemo.txt"), "rw");
for (int i = 0; i < 10; i++) {
    System.out.println("Value:" + i + ": " + raf.readInt());
}
raf.close();

// 重新獲取隨機訪問文件對象
raf = new RandomAccessFile(new File("randomFileDemo.txt"), "rw");
// 設(shè)置文件指針偏移量,從0開始,直接將文件指針移到第6個int數(shù)據(jù)后面(1個int占4個字節(jié))
raf.seek(5 * 4);
//覆蓋第6個int數(shù)據(jù)
raf.writeInt(16);
raf.close();

System.out.println("================修改后的內(nèi)容===============" );
// 重新獲取隨機訪問文件對象
raf = new RandomAccessFile(new File("randomFileDemo.txt"), "rw");
for (int i = 0; i < 10; i++) {
    System.out.println("Value:" + i + ": " + raf.readInt());
}
raf.close();

輸出結(jié)果:

================修改前的內(nèi)容===============
Value:0: 0
Value:1: 1
Value:2: 2
Value:3: 3
Value:4: 4
Value:5: 5
Value:6: 6
Value:7: 7
Value:8: 8
Value:9: 9
================修改后的內(nèi)容===============
Value:0: 0
Value:1: 1
Value:2: 2
Value:3: 3
Value:4: 4
Value:5: 16
Value:6: 6
Value:7: 7
Value:8: 8
Value:9: 9

RandomAccessFile類為用戶提供了兩種構(gòu)造方法,具體操作方式如下:

// 第一種構(gòu)造方法:指定 file 對象和讀寫模式
RandomAccessFile raf = new RandomAccessFile(File file, String mode);

// 第二種構(gòu)造方法:指定 filename 路徑和讀寫模式
RandomAccessFile raf = new RandomAccessFile(String filename, String mode);

其實第二種構(gòu)造方法也是new File()出來,再調(diào)用第一種構(gòu)造方法,兩者都可以獲取隨機訪問文件對象。

至于mode,表示以何種方式打開文件,Java給開發(fā)者提供了四種mode值,具體解釋如下!

圖片圖片

值得注意的地方是,**"rw"模式下,Java 并不強求指定的路徑下一定存在某個文件,假如文件不存在,會自動創(chuàng)建**。

RandomAccessFile類為用戶提供的方法比較多,我們可以關(guān)注下幾個重要的方法即可,詳細方法如下圖!

圖片圖片

方法的使用,可以參考如下樣例:

RandomAccessFile file = new RandomAccessFile("file.txt", "rw");
// 以下向file文件中寫數(shù)據(jù)
file.writeInt(20);// 占4個字節(jié)
file.writeDouble(8.236598);// 占8個字節(jié)
file.writeUTF("這是一個UTF字符串");// 這個長度寫在當前文件指針的前兩個字節(jié)處,可用readShort()讀取
file.writeBoolean(true);// 占1個字節(jié)
file.writeShort(395);// 占2個字節(jié)
file.writeLong(2325451L);// 占8個字節(jié)
file.writeUTF("又是一個UTF字符串");
file.writeFloat(35.5f);// 占4個字節(jié)
file.writeChar('a');// 占2個字節(jié)

file.seek(0);// 把文件指針位置設(shè)置到文件起始處

// 以下從file文件中讀數(shù)據(jù),要注意文件指針的位置
System.out.println("——————從file文件指定位置讀數(shù)據(jù)——————");
System.out.println(file.readInt());
System.out.println(file.readDouble());
System.out.println(file.readUTF());

file.skipBytes(3);// 將文件指針跳過3個字節(jié),本例中即跳過了一個boolean值和short值。
System.out.println(file.readLong());

file.skipBytes(file.readShort()); // 跳過文件中“又是一個UTF字符串”所占字節(jié),注意readShort()方法會移動文件指針,所以不用加2。
System.out.println(file.readFloat());

//以下演示文件復制操作
System.out.println("——————文件復制(從file到fileCopy)——————");
file.seek(0);
RandomAccessFile fileCopy=new RandomAccessFile("fileCopy.txt","rw");
int len=(int)file.length();//取得文件長度(字節(jié)數(shù))
byte[] b=new byte[len];
file.readFully(b);//讀取全部內(nèi)容
fileCopy.write(b);//全部寫入目標文件
System.out.println("復制完成!");

根據(jù)以上的方法介紹,我們可以利用RandomAccessFile實現(xiàn)一個在任意位置插入數(shù)據(jù)的操作,具體實例如下:

public class RandomAccessFileTest1 {

    /**
     * 插入數(shù)據(jù)
     * @param skip 跳過多少過字節(jié)進行插入數(shù)據(jù)
     * @param str 要插入的字符串
     * @param fileName 文件路徑
     */
    public static void insert(long skip, String str, String fileName){
        try {
            RandomAccessFile raf = new RandomAccessFile(fileName,"rw");
            if(skip <  0 || skip > raf.length()){
                System.out.println("跳過字節(jié)數(shù)無效");
                return;
            }
            byte[] b = str.getBytes();
            raf.setLength(raf.length() + b.length);
            // 將尾部數(shù)據(jù)進行遷移
            for(long i = raf.length() - 1; i > b.length + skip - 1; i--){
                raf.seek(i - b.length);
                byte temp = raf.readByte();
                raf.seek(i);
                raf.writeByte(temp);
            }
            // 從指定的位置,開始覆寫數(shù)據(jù)
            raf.seek(skip);
            raf.write(b);
            raf.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 方法測試
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) {
        insert(0, "一起學習Java", "test.txt");
        insert(0, "Hello,", "test.txt");
    }
}

文件內(nèi)容結(jié)果如下:

Hello,一起學習Java

三、RandomAccessFile 類的應用

在實際的開發(fā)過程中,RandomAccessFile 的一個重要應用場景就是網(wǎng)絡(luò)請求中的文件多線程下載及斷點續(xù)傳。

首先將文件分成幾塊,然后每塊用不同的線程進行下載,下面是一個利用多線程在寫文件時的例子:

public class RandomAccessFileTest2 {

    public static void main(String[] args) throws Exception {
        // 預分配文件所占的磁盤空間,磁盤中會創(chuàng)建一個指定大小的文件
        RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");
        raf.setLength(1024*1024); // 預分配 1M 的文件空間
        raf.close();

        // 所要寫入的文件內(nèi)容
        String s1 = "第一個字符串";
        String s2 = "第二個字符串";
        String s3 = "第三個字符串";
        String s4 = "第四個字符串";
        String s5 = "第五個字符串";

        // 利用多線程同時寫入一個文件
        new FileWriteThread(1024*1,s1.getBytes()).start(); // 從文件的1024字節(jié)之后開始寫入數(shù)據(jù)
        new FileWriteThread(1024*2,s2.getBytes()).start(); // 從文件的2048字節(jié)之后開始寫入數(shù)據(jù)
        new FileWriteThread(1024*3,s3.getBytes()).start(); // 從文件的3072字節(jié)之后開始寫入數(shù)據(jù)
        new FileWriteThread(1024*4,s4.getBytes()).start(); // 從文件的4096字節(jié)之后開始寫入數(shù)據(jù)
        new FileWriteThread(1024*5,s5.getBytes()).start(); // 從文件的5120字節(jié)之后開始寫入數(shù)據(jù)
    }
}

class FileWriteThread extends Thread{
    private int skip;
    private byte[] content;

    public FileWriteThread(int skip,byte[] content){
        this.skip = skip;
        this.content = content;
    }

    @Override
    public void run(){
        RandomAccessFile raf = null;
        try {
            // 利用線程在文件的指定位置寫入指定數(shù)據(jù)
            raf = new RandomAccessFile("test.txt", "rw");
            raf.seek(skip);
            raf.write(content);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                raf.close();
            } catch (Exception e) {
            }
        }
    }
}

四、小結(jié)

本文主要圍繞 RandomAccessFile 類的基本概念和常用方法,做了一次簡單的知識總結(jié),該類是 IO 流體系中功能最豐富的文件內(nèi)容訪問類,既可以讀取文件中任意位置的內(nèi)容,也可以向文件任意位置寫入數(shù)據(jù)。

當然 RandomAccessFile 當讀寫大文件的時候,會出現(xiàn)內(nèi)存溢出問題,此時可以采用內(nèi)存映射文件方式進行讀寫數(shù)據(jù),關(guān)于技術(shù)會在后期的文章中進行介紹。

責任編輯:武曉燕 來源: Java極客技術(shù)
相關(guān)推薦

2010-01-27 16:41:43

2014-12-26 20:46:18

惠普HP Mobile C

2016-01-08 19:34:14

新東方

2024-08-23 09:06:26

2010-03-04 16:42:59

2010-07-16 10:42:14

telnet批處理

2009-12-31 11:27:33

2021-02-26 20:55:56

JavaNIO隨機

2010-08-30 20:18:28

DHCP服務(wù)器

2021-08-05 10:00:02

Python編程語言

2021-07-19 09:51:55

智能語音移動云

2010-02-25 14:50:59

Linux文件系統(tǒng)

2011-10-21 09:06:41

Better Net銳捷網(wǎng)絡(luò)

2010-07-16 09:06:57

Perl文件

2010-11-19 11:32:25

Oracle存儲過程

2013-05-27 10:58:10

propertiesJava語言

2021-04-02 06:35:49

Bash讀寫文件Linux

2009-12-22 10:05:00

Linux文件系統(tǒng)

2012-06-20 14:16:36

Java內(nèi)存映射
點贊
收藏

51CTO技術(shù)棧公眾號