Windows上,內存映射文件,使得大文件的讀寫不會消耗太多的內存,也減少了頻繁的cpu指令。另外,windows上的進程間共享數據,也是通過內存映射文件的方式來實現。
剛好又遇到這個需求,需要在服務器上一次載入幾十兆大小的文件,每個文件大約有100萬條數據。所以溫習一下這塊內容。
使用內存映射文件,需要按下列操作步驟操作:
1,打開一個文件對象,也就是文件句柄了。
2,創建一個文件映射對象 。
3,獲取文件映射對象在進程地址空間的指針。
當完成對內存映射文件操作時,執行下面這些步驟清理內存:
1,告訴系統從你的進程的地址空間中撤消文件映射內核對象的映像。
2,關閉文件映射對象。
3,關閉文件句柄。
內存映射可以高效的對大文件進行讀寫操作,可以這樣理解,這個文件在物理磁盤上的存儲空間被作爲虛擬內存使用了,你讀寫這塊內存區域,就相當於讀寫文件。在效率上,比I/O文件系統高了很多。win32上的進程間消息傳遞SendMessage和PostMessage都是用到這種方法。
實際上如果只是單純使用它,就不必深究原理,否則需要去看《Windows核心編程》。
代碼是硬道理:
假設在E盤有一個測試文件test.txt,內容如下:
- #include "windows.h"
- #include "stdio.h"
- int main()
- {
- //文件對象
- TCHAR STR[] = "hello world!";
- HANDLE hFile = CreateFile("E:\\test.txt",
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- //映射對象
- HANDLE hFileMapping = CreateFileMapping(hFile,
- NULL,
- PAGE_READWRITE,
- 0,
- 0,
- NULL);
- //這裏賦值了2個文件映射的指針,地址從文件頭開始
- TCHAR *pbFile1 = (TCHAR *)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);
- TCHAR *pbFile2 = (TCHAR *)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);
- /*
- 輸出字符串的內容,可以看到的是,把整個文件當作字符串輸出了。
- 當然,如果文件中含有'\0'的字符,你看不到全部文件內容的輸出。
- */
- //兩個輸出的結果是一樣的
- printf("%s\n", pbFile1);
- printf("%s\n", pbFile2);
- /*
- 下面的操作是往這個pbFile1指向的地址寫入點自定義的內容,
- 然後比較pbFile2指向地址的值是否相應改變了。
- */
- memcpy(pbFile1, STR, strlen(STR));
- printf("%s\n", pbFile1);
- printf("%s\n", pbFile2);
- //清理指針和內存
- UnmapViewOfFile(pbFile1);
- UnmapViewOfFile(pbFile2);
- CloseHandle(hFileMapping);
- CloseHandle(hFile);
- return 0;
- }