Java IO學習筆記三:MMAP與RandomAccessFile


作者:Grey

原文地址:Java IO學習筆記三:MMAP與RandomAccessFile

關於RandomAccessFile

相較於前面提到的BufferedReader/Writer和FileReader/Writer

普通的ReaderWriter只能順序讀寫數據,RandomAccessFile提供了一個獨有的seek方法,可以修改文件內容的指針,從而可以方便讀取和修改文件中的任意位置。示例:

import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

import static java.nio.charset.StandardCharsets.UTF_8;

public class TestRandomAccessFile {

    public static void main(String[] args) {
        String path = "C:\\workspace\\out.txt";
        try {
            RandomAccessFile randomAccessFile = new RandomAccessFile(path, "rw");
            randomAccessFile.write("Hello xxxld".getBytes(UTF_8));
            randomAccessFile.seek(6);
            randomAccessFile.write("Wor".getBytes(UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

seek(6)讓指針跳到"Hello xxld"這個字符串中的第一個"x"的位置,再次寫入"Wor"這個字符串(覆蓋寫)

所以返回的結果是:

Hello World

關於MMAP

關於mmap,可以參考這篇文章的介紹認真分析mmap:是什么 為什么 怎么用

mmap是一種內存映射文件的方法,即將一個文件或者其它對象映射到進程的地址空間,實現文件磁盤地址和進程虛擬地址空間中一段虛擬地址的一一對映關系。實現這樣的映射關系后,進程就可以采用指針的方式讀寫操作這一段內存,而系統會自動回寫臟頁面到對應的文件磁盤上,即完成了對文件的操作而不必再調用read,write等系統調用函數。相反,內核空間對這段區域的修改也直接反映用戶空間,從而可以實現不同進程間的文件共享。

以及從內核文件系統看文件讀寫過程

通過RandomAccessFile可以拿到文件的FileChannel,並做內存映射(底層就是MMAP,因為文件是塊設備,可以來回自由尋址,所以只有FileChannel才能做內存映射),即:把內核的pagecache和文件的數據地址空間映射起來。


    public static void testRandomAccessFileIO() throws Exception {
        String path = "C:\\workspace\\out.txt";
        byte[] data = "1234567\n".getBytes();
        RandomAccessFile file = new RandomAccessFile(path, "rw");
        FileChannel channel = file.getChannel();
        int size = 4096 * 100;
        MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE, 0, size);
        while (size != 0) {
            map.put(data);
            size -= data.length;
        }
        map.force();
    }

其中

 channel.map(FileChannel.MapMode.READ_WRITE, 0, size);

通過mmap生成的且是堆外的和文件映射的內存區域

原先我們的FileWriter需要通過write方法才能將數據寫入pagecache,現在只需要通過map.put方法即可。

其中

map.force()

方法就等同於File中的

file.flush()

方法

將內容從主存寫入磁盤中。

源碼

Github


免責聲明!

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



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