處理幾十 MB 至數 GB 文件時,fread/ReadFile 等傳統方式涉及:用戶態/核心態切換、資料拷貝(核心緩衝→用戶緩衝)、頻繁系統調用。CPU、記憶體、I/O 三重壓力,效能急劇下降。
將文件直接映射至進程虛擬地址空間,以指標方式直接存取文件內容。OS 自動處理頁面調度、預讀、寫回,實現零拷貝、隨機存取、共享記憶體等優勢。
CreateFile 取得文件句柄CreateFileMapping 建立映射對象MapViewOfFile 映射視圖至位址空間,獲得指標 lpBaselpBase 指標讀寫資料UnmapViewOfFile、CloseHandle 清理文件格式:KEY=VALUE\r\n,25 萬行、15 MB。傳統 map<string,string> 佔用 70+ MB 記憶體、載入極慢。
映射檔方案:不載入容器,直接指標掃描。
HANDLE hFile = CreateFile("C:/test.tsr", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
SYSTEM_INFO si; GetSystemInfo(&si);
DWORD granularity = si.dwAllocationGranularity;
DWORD dwSizeHigh;
LONGLONG fileSize = GetFileSize(hFile, &dwSizeHigh);
fileSize |= ((LONGLONG)dwSizeHigh << 32);
CloseHandle(hFile);
DWORD viewSize = (fileSize < 1000*granularity) ? (DWORD)fileSize : 1000*granularity;
TCHAR* pView = (TCHAR*)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, viewSize);
// 查找函數:純指標操作,無額外記憶體分配
string GetValue(const TCHAR* base, const TCHAR* key) {
TCHAR* p1 = strstr(base, key);
if (!p1) return "";
TCHAR* p2 = strstr(p1, "\r\n");
if (p2) *p2 = '\0';
string val = p1 + strlen(key) + 1; // 跳過 "KEY="
if (p2) *p2 = '\r'; // 還原
return val;
}
// 使用
cout << GetValue(pView, "SEU07201213") << endl;
// 清理
UnmapViewOfFile(pView);
CloseHandle(hMap);
| 方案 | 記憶體佔用 | 查找耗時 (25萬行) |
|---|---|---|
| STL map 預載入 | 70+ MB | 極慢(含建構開銷) |
| Memory Mapped File + 指標掃描 | 近 0 額外進程記憶體 | < 1 秒 |
MapViewOfFile 偏移量需為系統分配粒度(通常 64KB)倍數。記憶體映射檔是 Windows 大文件處理的利器:**以虛擬記憶體機制替代手動緩衝管理**,實現高效、低記憶體佔用、代碼簡潔的文件隨機存取。掌握此技術,輕松應對 GB 級文本/二進制文件處理場景。