最近閒來無聊,想寫乙個簡單的檔案操作的類。但是由於經驗尚淺,對於類的設計總是把握的不是太好。
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提供的記憶體對映檔案為我們提供解決問題的途徑。...