讀取乙個大檔案的高效的方法

2021-06-21 23:43:28 字數 2333 閱讀 4551

記憶體對映   

最為基本的功能之一,win32 api和mfc均提供有支援檔案處理的函式和類,常用的有win32 api的createfile()、writefile()、readfile()和mfc提供的cfile類等。一般來說,以上這些函式可以滿足大多數場合的要求,但是對於某些特殊應用領域所需要的動輒幾十gb、幾百gb、乃至幾tb的海量儲存,再以通常的檔案處理方法進行處理顯然是行不通的。目前,對於上述這種大檔案的操作一般是以記憶體對映檔案的方式來加以處理的,本文下面將針對這種windows核心程式設計技術展開討論。

記憶體對映檔案概述

記憶體檔案對映也是windows的一種記憶體管理方法,提供了乙個統一的記憶體管理特徵,使應用程式可以通過記憶體指針對磁碟上的檔案進行訪問,其過程就如同對載入了檔案的記憶體的訪問。通過檔案對映這種使磁碟檔案的全部或部分內容與程序虛擬位址空間的某個區域建立對映關聯的能力,可以直接對被對映的檔案進行訪問,而不必執行檔案i/o操作也無需對檔案內容進行緩衝處理。記憶體檔案對映的這種特性是非常適合於用來管理大尺寸檔案的。

在使用記憶體對映檔案進行i/o處理時,系統對資料的傳輸按頁面來進行。至於內部的所有記憶體頁面則是由虛擬記憶體管理器來負責管理,由其來決定記憶體頁面何時被分頁到磁碟,哪些頁面應該被釋放以便為其它程序提供空閒空間,以及每個程序可以擁有超出實際分配物理記憶體之外的多少個頁面空間等等。由於虛擬記憶體管理器是以一種統一的方式來處理所有磁碟i/o的(以頁面為單位對記憶體資料進行讀寫),因此這種優化使其有能力以足夠快的速度來處理記憶體操作。

使用記憶體對映檔案時所進行的任何實際i/o互動都是在記憶體中進行並以標準的記憶體位址形式來訪問。磁碟的週期性分頁也是由作業系統

在後台隱蔽實現的,對應用程式而言是完全透明的。記憶體對映檔案的這種特性在進行大檔案的磁碟事務操作時將獲得很高的效益。

需要說明的是,在系統的正常的分頁操作過程中,記憶體對映檔案並非一成不變的,它將被定期更新。如果系統要使用的頁面目前正被某個記憶體對映檔案所占用,系統將釋放此頁面,如果頁面資料尚未儲存,系統將在釋放頁面之前自動完成頁面資料到磁碟的寫入。

對於使用頁虛擬儲存管理的windows作業系統,記憶體對映檔案是其內部已有的記憶體管理元件的乙個擴充。由可執行**頁面和資料頁面組成的應用程式可根據需要由作業系統來將這些頁面換進或換出記憶體。如果記憶體中的某個頁面不再需要,作業系統將撤消此頁面原擁用者對它的控制權,並釋放該頁面以供其它程序使用。只有在該頁面再次成為需求頁面時,才會從磁碟上的可執行檔案重新讀入記憶體。同樣地,當乙個程序初始化啟動時,記憶體的頁面將用來儲存該應用程式的靜態、動態資料,一旦對它們的操作被提交,這些頁面也將被備份至系統的頁面檔案,這與可執行檔案被用來備份執行**頁面的過程是很類似的。圖1展示了**頁面和資料頁面在磁碟儲存器上的備份過程:

圖1 程序的**頁、資料頁在磁碟儲存器上的備份

顯然,如果可以採取同一種方式來處理**和資料頁面,無疑將會提高程式的執行效率,而記憶體對映檔案的使用恰恰可以滿足此需求。

對大檔案的管理

記憶體對映檔案物件在關閉物件之前並沒有必要撤銷記憶體對映檔案的所有檢視。在物件被釋放之前,所有的髒頁面將自動寫入磁碟。通過closehandle()關閉記憶體對映檔案物件,只是釋放該物件,如果記憶體對映檔案代表的是磁碟檔案,那麼還需要呼叫標準檔案i/o函式來將其關閉。在處理大檔案處理時,記憶體對映檔案將表示出卓越的優勢,只需要消耗極少的物理資源,對系統的影響微乎其微。下面先給出記憶體對映檔案的一般程式設計流程框圖:

圖2 使用記憶體對映檔案的一般流程

而在某些特殊行業,經常要面對十幾gb乃至幾十gb容量的巨型檔案,而乙個32位程序所擁有的虛擬位址空間只有232 = 4gb,顯然不能一次將檔案映像全部對映進來。對於這種情況只能依次將大檔案的各個部分對映到程序中的乙個較小的位址空間。這需要對上面的一般流程進行適當的更改:

1)對映檔案開頭的映像。

2)對該映像進行訪問。

3)取消此映像

4)對映乙個從檔案中的乙個更深的位移開始的新映像。

5)重複步驟2,直到訪問完全部的檔案資料。

下面給出一段根據此描述而寫出的對大於4gb的檔案的處理**:

1)對映檔案開頭的映像。

2)對該映像進行訪問。

3)取消此映像

4)對映乙個從檔案中的乙個更深的位移開始的新映像。

5)重複步驟2,直到訪問完全部的檔案資料。

下面給出一段根據此描述而寫出的對大於4gb的檔案的處理**:

區保護屬性 說明

sec_commit

為區中的所有頁面在記憶體中或磁碟頁面檔案中分配物理儲存器

sec_image

告知系統,對映的檔案是乙個可移植的exe檔案映像

sec_nocache

告知系統,未將檔案的任何記憶體對映檔案放入快取記憶體,多供硬體

裝置驅動程式

開發人員使用

sec_reserve

對乙個區的所有頁面進行保留而不分配物理儲存器

dd命令建立乙個大檔案

dd命令可以建立指定大小的檔案 命令 dd if dev zero of test bs 1m count 1000 會在當前目錄下生成乙個大小為1m 1000 1000m大小的test.img檔案,它的內容都是0 因從 dev zero中讀取,dev zero為0源 if 輸入檔案 of 輸出檔案...

php如何高效的讀取大檔案

通常來說在php讀取大檔案的時候,我們採用的方法一般是一行行來讀取,而不是一次性把檔案全部寫入記憶體中,這樣會導致php程式卡死,下面就給大家介紹這樣乙個例子。需求 有乙個800m的日誌檔案,大約有500多萬行,用php返回最後幾行的內容。實現方法 取檔案最後 n行 param string fil...

在乙個大檔案中取得需要的資料

在linux下有乙個檔案,其中資料是按行報錯的,需要取出想要的資料 第一步 將其中需要匯出的行先導出 sudo grep preg.log result.txt 上面的意思是將所有包含豎線的行匯出到result.txt檔案。第二步 將result.txt中重複的行去重 cat result.txt ...