成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

一、摘要

RandomAccessFile 類,也被稱為隨機(jī)訪問文件類。

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

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

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

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

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

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

二、RandomAccessFile 類基本介紹

下面先來看看一個(gè)簡單的例子。

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

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

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

System.out.println("================修改后的內(nèi)容===============" );
// 重新獲取隨機(jī)訪問文件對象
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);

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

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

圖片圖片

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

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

圖片圖片

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

RandomAccessFile file = new RandomAccessFile("file.txt", "rw");
// 以下向file文件中寫數(shù)據(jù)
file.writeInt(20);// 占4個(gè)字節(jié)
file.writeDouble(8.236598);// 占8個(gè)字節(jié)
file.writeUTF("這是一個(gè)UTF字符串");// 這個(gè)長度寫在當(dāng)前文件指針的前兩個(gè)字節(jié)處,可用readShort()讀取
file.writeBoolean(true);// 占1個(gè)字節(jié)
file.writeShort(395);// 占2個(gè)字節(jié)
file.writeLong(2325451L);// 占8個(gè)字節(jié)
file.writeUTF("又是一個(gè)UTF字符串");
file.writeFloat(35.5f);// 占4個(gè)字節(jié)
file.writeChar('a');// 占2個(gè)字節(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個(gè)字節(jié),本例中即跳過了一個(gè)boolean值和short值。
System.out.println(file.readLong());

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

//以下演示文件復(fù)制操作
System.out.println("——————文件復(fù)制(從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);//全部寫入目標(biāo)文件
System.out.println("復(fù)制完成!");

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

public class RandomAccessFileTest1 {

    /**
     * 插入數(shù)據(jù)
     * @param skip 跳過多少過字節(jié)進(jìn)行插入數(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ù)進(jìn)行遷移
            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, "一起學(xué)習(xí)Java", "test.txt");
        insert(0, "Hello,", "test.txt");
    }
}

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

Hello,一起學(xué)習(xí)Java

三、RandomAccessFile 類的應(yīng)用

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

首先將文件分成幾塊,然后每塊用不同的線程進(jìn)行下載,下面是一個(gè)利用多線程在寫文件時(shí)的例子:

public class RandomAccessFileTest2 {

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

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

        // 利用多線程同時(shí)寫入一個(gè)文件
        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ù)。

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

責(zé)任編輯:武曉燕 來源: 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批處理

2010-08-30 20:18:28

DHCP服務(wù)器

2009-12-31 11:27:33

2021-02-26 20:55:56

JavaNIO隨機(jī)

2021-07-19 09:51:55

智能語音移動(dòng)云

2010-02-25 14:50:59

Linux文件系統(tǒng)

2021-08-05 10:00:02

Python編程語言

2009-12-22 10:05:00

Linux文件系統(tǒng)

2021-07-15 10:14:37

網(wǎng)絡(luò)安全漏洞攻擊

2021-04-27 13:56:49

內(nèi)存.映射地址

2010-05-10 14:15:54

DNS負(fù)載均衡

2010-08-26 13:38:45

DHCP冗余

2011-10-21 09:06:41

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

2010-03-01 14:46:41

Linux hostn
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 久久国产精品-国产精品 | 国产一区二 | 区一区二在线观看 | 999在线精品 | 国产精品乱码一二三区的特点 | 精品1区2区3区4区 | 欧美日韩a | 欧美xxxx网站 | 精品伊人 | jizz中国日本 | 国产成人精品网站 | 一级一片在线观看 | av免费网站在线 | 六月色婷| 在线看91 | 欧美成人综合 | 日韩欧美精品一区 | 亚洲一区国产精品 | 91精品国产综合久久小仙女图片 | 一区二区伦理电影 | 久久三区 | 在线一区视频 | 2019中文字幕视频 | caoporn免费 | 男人天堂网址 | 狠狠躁夜夜躁人人爽天天高潮 | 成人性视频在线播放 | 黄网站免费在线看 | 卡通动漫第一页 | 成人国产精品一级毛片视频毛片 | 久草热线| 一级看片免费视频 | 成人在线h | 精品在线视频播放 | 亚洲视频在线一区 | 成人影院在线观看 | 91久久 | 国产精品美女久久久久久免费 | 亚洲黄色在线 | 成人深夜小视频 | 亚洲高清av在线 |