利用記憶體對映處理檔案

2021-05-24 09:18:20 字數 2575 閱讀 2640

最近閒來無聊,想寫乙個簡單的檔案操作的類。但是由於經驗尚淺,對於類的設計總是把握的不是太好。

c++畢竟是物件導向,而且自己又學過設計模式(個人覺得這個非常有用),當然也就希望自己設計的類有物件的意味了。

學習的最好方法就是模仿,在我印象中c#.net框架中的類設計的很好,就借鑑一下。

.net中操作檔案的類如下:

filestream:提供乙個訪問檔案流對檔案進行讀寫、開啟、關閉等操作

streamreader:用於讀取文字資訊。他會檢查位元組標記確定編碼方法,當然也可以制定編碼方法。

file,fileinfo:提供對檔案本身整體的操作,例如,建立、複製、刪除、移動等,也負責檔案的屬性控制,例如查詢建立時間

、檔案大小等。

編碼之前需要做一些前期工作,那就是設計,設計之前我草擬了一些原則:

1、引數不宜超過4個,且每個引數的意義要盡量簡單

2、方法盡可能簡單,意義明確

3、高內聚、低耦合,例如可將對檔案流的編譯碼**分離出來

4、每個類盡可能的功能單一,方法數量不宜過多。例如檔案讀取類streamreader只提供讀取檔案的相關操作,至於對檔案屬性的查詢

絕對不能放到這個類中

5、對於節本的讀寫檔案類,應忽略檔案結構

6、方法的引數、返回值統一為寬位元組,採用unicode編碼。

經過一番思考,初期設計如下:

1、filestream:負責檔案的讀寫、開啟、關閉操作。讀寫都面向位元組流,具體來說就是此類負責檔案的開啟,然後以位元組形式讀寫。

2、encoding:負責字元的編譯碼操作。

下面是乙個介面的設計

class  ifileiostream

;剛開始設計比較簡單,實現都是用檔案操作的api函式實現的,但是發現效率非常低。例如讀取10萬字的文字檔案,

需要1055毫秒,後來採用記憶體對映實現,時間縮短到了十分之一。於是乾脆把cfilestream用記憶體對映來實現

class cfilestream:public ifileiostream

;public:

//方法

bool open(lpctstr lpname,dword dwcreate = open_existing, dword dwsharemode = 0);

bool isopen();

void close();

bool flush();

dword seek(long ldistancetomove,dword dwmovorigion);

dword read(lpbyte lpbuffer,dword dwlengthtoread);

bool readbyte(byte & pbyte);

dword write(lpbyte lpbuffer,dword dwlengthtowrite);

bool writebyte(byte bbyte);

//屬性

public:

//如果引數lpname為null則函式返回檔名的所需空間大小,否則lpname返回檔名,並返回檔名大小

int getname(lpctstr lpname);

//檔案的大小(位元組數)

dword getfilesize()

//當前檔案指標位置(相對於檔案頭的偏移)

dword getposition();

handle gethandle()

private:

bool beginmap(handle hfile);

void copyfrom(cfilestream &anotherfilestream);

void growfilesize();

private:

handle m_hfile;

handle m_hmapfile;

lpbyte m_pbbegin;

lpbyte m_pbdata;

lpbyte m_pbend;

cfilestream * m_pparentstream;

tchar m_tchname[file_max_name_length];

dword m_dwsize;

bool m_bopen;

bool m_bopentoread;

};但是在寫檔案的時候出現了很大的問題,由於記憶體對映物件的大小事先是確定了的,這樣就非常不利於檔案的擴充套件。

例如檔案只有4k大小,當寫入第4k+1個位元組時候就出現了問題!如果用writefile這個api,則系統會自動擴充套件檔案大小,而用記憶體

對映就不行了。

解決辦法由三種:

1、當寫到檔案末尾時候,重新進行對映,將記憶體對映物件大小增加乙個4k,這樣可自動擴充套件檔案大小。但是這出現了乙個問題,

例如當總共寫入4k+1個位元組,擴充套件後原檔案大小為8k,且剩下的4k-1全是0,而不像用writefile那樣在4k+1後有個檔案結束符。

這是因為在取消對映時,系統將8k的資料全部寫入了檔案中。

2、寫檔案仍然呼叫writefile。這樣犧牲了效率

3、使用網上說的方法,用乙個臨時檔案,超出檔案尾的資料,寫到另乙個記憶體對映物件中,操作結束時,將資料寫回到原檔案中。

其中第二種方法最易實現。

大檔案處理 記憶體檔案對映

記憶體對映檔案,是由乙個檔案到一塊記憶體的對映。與虛擬記憶體有些類似,通過記憶體對映檔案可以保留乙個位址空間的區域,同時將物理儲存器提交給此區域,記憶體檔案對映的物理儲存器來自乙個已經存在的磁碟上的檔案,而且在對該檔案進行操作之前必須首先對檔案進行對映。另外,記憶體對映檔案是由乙個檔案到程序位址空間...

記憶體對映檔案機制處理大檔案

原文 hongchangfirst hongchangfirst的主頁 先說結論 使用記憶體對映檔案來處理大檔案可以提高效率。為什麼呢?我們先來看看如果不使用記憶體對映檔案的處理流程是怎樣的,首先我們得先讀出磁碟檔案的內容到記憶體中,然後修改,最後回寫到磁碟上。第一步讀磁碟檔案是要經過一次系統呼叫的...

利用記憶體對映檔案擴充程式可用的記憶體

windows利用頁交換檔案來擴充應用程式實際可用的記憶體,而不僅限於實際的32兆或64兆物理記憶體。但是windows的頁交換檔案是所有程式共用的,所以我們的程式要想獲得更大的記憶體還是比較困難,比如600兆或者更多。難道就沒有辦法了嗎?windows提供的記憶體對映檔案為我們提供解決問題的途徑。...