本人在學習《WINDOWS核心編程》的時候對JEFFREY大師提到的一個小程序寫了兩個版本來比較性能,該程序的原始需求是這樣的:對一個大文件進行倒序,也就是將一個文件頭變成尾,尾變成頭。
使用的方法有很多種,這里使用兩個方法來比較,主要是突出使用內存映射文件好處;兩種方法為:內存映射文件方法,I/O讀寫的緩存辦法。
第一種辦法是創建內存映射文件對象,然后將該對象映射到進程的地址空間中,再讀取文件內容,然后倒序,再寫入文件。
第二中方法是,將文件內容讀入一個大的緩沖區,然后倒序,再寫入文件,中間對原來的文件刪除,然后重新寫入。
程序編寫如下
第一種方法,內存映射文件方式:
BOOL FileReverse(PCTSTR pszPathName) { HANDLE hFile = CreateFile(pszPathName,GENERIC_WRITE|GENERIC_READ,0,NULL ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile == INVALID_HANDLE_VALUE) { printf("File could not be opened."); return FALSE; }
DWORD dwFileSize = GetFileSize(hFile,NULL);
HANDLE hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0, dwFileSize+sizeof(char),NULL);
if(hFileMap == NULL){ CloseHandle(hFile); return FALSE; }
PVOID pvFile = MapViewOfFile(hFileMap,FILE_MAP_WRITE,0,0,0);
if(pvFile == NULL){ CloseHandle(hFileMap); CloseHandle(hFile); return FALSE; }
PSTR pchAnsi = (PSTR)pvFile; pchAnsi[dwFileSize/sizeof(char)]=0; _strrev(pchAnsi);
pchAnsi = strchr(pchAnsi,'\n'); while(pchAnsi != NULL){ *pchAnsi++ ='\r'; *pchAnsi++ ='\n'; pchAnsi = strchr(pchAnsi,'\n'); }
UnmapViewOfFile(pvFile); CloseHandle(hFileMap);
SetFilePointer(hFile,dwFileSize,NULL,FILE_BEGIN); SetEndOfFile(hFile);//實際上不需要寫入了。 CloseHandle(hFile);
return TRUE; }
第二中方法,使用緩存的方式:
BOOL FileReverseNoMap(PCTSTR pszPathName) { HANDLE hFile = CreateFile(pszPathName,GENERIC_WRITE|GENERIC_READ,0,NULL ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile == INVALID_HANDLE_VALUE) { printf("File could not be opened."); return FALSE; }
DWORD dwFileSize = GetFileSize(hFile,NULL); //CloseHandle(hFile); char *readBuf = new char[dwFileSize+1]; DWORD nRead = 0,nRet =0; while(nRead if(ReadFile(hFile,readBuf+nRead,dwFileSize-nRead,&nRet,NULL) ==TRUE) { nRead+= nRet; } else { printf("Can read the file!"); CloseHandle(hFile); } }
PSTR pchAnsi = (PSTR)readBuf; pchAnsi[dwFileSize/sizeof(char)]=0; _strrev(pchAnsi);
pchAnsi = strchr(pchAnsi,'\n'); while(pchAnsi != NULL){ *pchAnsi++ ='\r'; *pchAnsi++ ='\n'; pchAnsi = strchr(pchAnsi,'\n'); } CloseHandle(hFile); DeleteFile(pszPathName);
HANDLE hWriteFile = CreateFile(pszPathName,GENERIC_WRITE|GENERIC_READ,0,NULL ,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); WriteFile(hWriteFile,readBuf,dwFileSize,&nRet,NULL); CloseHandle(hWriteFile);
delete readBuf;
return TRUE; }
本人測試機器的CPU是迅池1.5的筆記本,內存為712MB
通過上面的測試我們可以看到使用內存映射文件的好處,在文件內存越大這種優勢就體現的越明顯,其中主要的原因是:
內存映射文件直接將文件的地址映射到進程的地址空間中,那么操作文件就相當于在內存中操作一樣,省去了讀和寫I/O的時間;第二種方式是必須這么做(READFILE,WRITEFILE),這個過程是很慢的。
|