国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

win32 磁盤文件的正常讀寫與異步讀寫

2019-11-08 01:56:19
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

在Win32系統(tǒng)下文件可以支持平常的同步讀寫和異步讀寫(但在Win9X下,Win32系統(tǒng)不支持磁盤文件的異步讀寫)。本節(jié)在后面部分將會(huì)介紹文件的異步讀寫,最后一段內(nèi)容將向大家講解一下文件的區(qū)域加鎖。

在Win32系統(tǒng)中支持64位長(zhǎng)度的文件,所以在很多文件操作函數(shù)中需要兩個(gè)DWord參數(shù)來(lái)表示文件長(zhǎng)度,一個(gè)DWORD用來(lái)表示低32位,另一個(gè)用來(lái)表示高32位。

文件的讀寫進(jìn)行在文件被正確打開后,但請(qǐng)確認(rèn)在打開文件時(shí)設(shè)置了正確的讀寫標(biāo)記。在Win32的文件操作中沒(méi)有了以前類似與以前ANSI C中的fputs fgets fPRintf fscanf等函數(shù),只有類似于fread和fwrite的ReadFile和WriteFile函數(shù)。

ReadFile用于文件讀,函數(shù)原型為:

BOOL ReadFile(  HANDLE hFile,                // handle to file  LPVOID lpBuffer,             // data buffer  DWORD nNumberOfBytesToRead,  // number of bytes to read  LPDWORD lpNumberOfBytesRead, // number of bytes read  LPOVERLAPPED lpOverlapped    // overlapped buffer);其中各項(xiàng)參數(shù)的含義為:hFile:文件句柄,為CreateFile時(shí)返回的句柄lpBuffer:保存讀入的數(shù)據(jù)的指針nNumberOfBytesToRead:指定需要讀入的字節(jié)數(shù)lpNumberOfBytesRead:返回實(shí)際讀入的字節(jié)數(shù)lpOverlapped:在文件異步讀寫時(shí)使用的數(shù)據(jù),在同步讀寫中全部都設(shè)置為NULL,在Win9X中只支持對(duì)串口的異步操作。如果返回值為FALSE并且讀入的字節(jié)數(shù)也返回為0,則表示文件到達(dá)了末尾。
WriteFile用于文件寫,函數(shù)原型為:BOOL WriteFile(  HANDLE hFile,                    // handle to file  LPCVOID lpBuffer,                // data buffer  DWORD nNumberOfBytesToWrite,     // number of bytes to write  LPDWORD lpNumberOfBytesWritten,  // number of bytes written  LPOVERLAPPED lpOverlapped        // overlapped buffer);參數(shù)的含義和ReadFile類似。

如果需要移動(dòng)文件指針到相關(guān)位置(和文件讀寫不同,這個(gè)函數(shù)沒(méi)有異步版本),使用

DWORD SetFilePointer(  HANDLE hFile,                // handle to file  LONG lDistanceToMove,        // bytes to move pointer  PLONG lpDistanceToMoveHigh,  // bytes to move pointer  DWORD dwMoveMethod           // starting point);其中各項(xiàng)參數(shù)的含義為:hFile:文件句柄,為CreateFile時(shí)返回的句柄lpBuffer:保存讀入的數(shù)據(jù)的指針lDistanceToMove:移動(dòng)的字節(jié)數(shù)低DWORDlpDistanceToMoveHigh:移動(dòng)的字節(jié)數(shù)高DWORD,為了支持64位(2的64次方字節(jié))長(zhǎng)度的大文件,而用來(lái)指定64字節(jié)的高32位,如果文件大小只需要32位就可以表示,則設(shè)置為NULLldwMoveMethod:移動(dòng)方法,可以選擇下面的值。FILE_BEGIN 從文件開始處開始移動(dòng)FILE_CURRENT 從文件開始除開始移動(dòng)FILE_END 從文件末尾開始移動(dòng)函數(shù)返回值和參數(shù)lpDistanceToMoveHigh(當(dāng)該參數(shù)不為NULL時(shí))表明文件指針當(dāng)前的位置(從文件頭到當(dāng)前的字節(jié)數(shù)),但當(dāng)參數(shù)lpDistanceToMoveHigh為NULL時(shí)如果返回INVALID_SET_FILE_POINTER表明執(zhí)行失敗,當(dāng)參數(shù)lpDistanceToMoveHigh不為NULL時(shí)如果返回INVALID_SET_FILE_POINTER還需要判斷GetLastError的返回值是否不為NO_ERROR。下面是兩種情況下判斷錯(cuò)誤。
//第一種情況DWORD dwPtr = SetFilePointer (hFile, lDistance, NULL, FILE_BEGIN) ;  if (dwPtr == INVALID_SET_FILE_POINTER) // Test for failure{     // Obtain the error code.     dwError = GetLastError() ;      // 處理錯(cuò)誤    // . . .  } // End of error handler //第二種情況dwPtrLow = SetFilePointer (hFile, lDistLow, & lDistHigh, FILE_BEGIN) ;  // Test for failureif (dwPtrLow == INVALID_SET_FILE_POINTER && (dwError = GetLastError()) != NO_ERROR ){     // 處理錯(cuò)誤     // . . . } // End of error handler 在Win32中沒(méi)有提供得到文件當(dāng)前指針位置的函數(shù),但通過(guò)SetFilePointer也可以確定文件指針當(dāng)前的位置。在MSDN中提供了兩個(gè)宏來(lái)得到當(dāng)前文件的指針位置:
//對(duì)32位長(zhǎng)度的文件    #define GetFilePointer(hFile) SetFilePointer(hFile, 0, NULL, FILE_CURRENT)//對(duì)超過(guò)32位長(zhǎng)度的文件    #define GetVLFilePointer(hFile, lpPositionHigh) /        (*lpPositionHigh = 0, /        SetFilePointer(hFile, 0, lpPositionHigh, FILE_CURRENT))對(duì)了可以通過(guò)SetFilePointer來(lái)得到文件長(zhǎng)度,方法就是從文件位結(jié)束處移動(dòng)0字節(jié),返回值就是文件的長(zhǎng)度。
HANDLE hFile = CreateFile(...);//打開文件進(jìn)行讀DWORD dwLen;dwLen = SetFilePointer (hFile, 0, NULL, FILE_END) ; CloseHandle( hFile ) ;當(dāng)然Win32中也提供了專門的函數(shù)來(lái)得到文件的大小
BOOL GetFileSizeEx(  HANDLE hFile,              // handle to file  PLARGE_INTEGER lpFileSize  // file size);typedef union _LARGE_INTEGER {   struct {      DWORD LowPart;       LONG  HighPart;   };  LONGLONG QuadPart;} LARGE_INTEGER, *PLARGE_INTEGER; 其中l(wèi)pFileSize是一個(gè)聯(lián)合數(shù)據(jù),用來(lái)表明文件的大小。

文件的異步讀寫主要是用在大文件的讀寫上,當(dāng)使用異步讀寫時(shí),ReadFile和WriteFile會(huì)馬上返回,并在讀寫完成時(shí)通知應(yīng)用程序。

要使用異步功能首先需要在打開文件時(shí)指定FILE_FLAG_OVERLAPPED作為標(biāo)記(dwFlagsAndAttributes),在讀寫文件時(shí)可以使用ReadFile/WriteFile或者ReadFileEx/WriteFileEx來(lái)進(jìn)行讀寫,當(dāng)調(diào)用不同的函數(shù)時(shí)讀寫完成后通知應(yīng)用程序的方法有所不同的,。下面分別介紹這兩種方法:

第一種方法,利用ReadFile/WriteFile,這對(duì)函數(shù)使用事件信號(hào)來(lái)進(jìn)行讀寫完成的通知,由于磁盤讀寫是一個(gè)比較耗費(fèi)時(shí)間的操作,而且現(xiàn)在的磁盤子系統(tǒng)可以在磁盤讀寫時(shí)脫離CPU而單獨(dú)進(jìn)行,例如使用DMA方式,所以在磁盤讀寫時(shí)可以進(jìn)行其他一些操作以充分利用CPU。關(guān)于事件信號(hào)相關(guān)內(nèi)容請(qǐng)參考4.4節(jié) 進(jìn)程/線程間同步中事件部分內(nèi)容。并且在文件讀寫時(shí)提供OVERLAPPED數(shù)據(jù)。

結(jié)構(gòu)定義如下:typedef struct _OVERLAPPED {     ULONG_PTR  Internal; //系統(tǒng)使用    ULONG_PTR  InternalHigh; //系統(tǒng)使用    DWORD  Offset; // 文件讀或?qū)懙拈_始位置低32位,對(duì)于命名管道和其他通信設(shè)備必須設(shè)置為0    DWORD  OffsetHigh; // 文件讀或?qū)懙拈_始位置高32位,對(duì)于命名管道和其他通信設(shè)備必須設(shè)置為0    HANDLE hEvent; // 事件量,當(dāng)操作完成時(shí),這個(gè)時(shí)間會(huì)變?yōu)橛行盘?hào)狀態(tài)} OVERLAPPED; //下面的代碼演示了文件異步讀取//并且比較了同步和異步之間的性能差異void DoDataDeal(BYTE *pbData,int iLen){//對(duì)字節(jié)進(jìn)行操作	Sleep(3*1000);//假設(shè)每次計(jì)算需要2秒鐘}//下面是使用異步讀的示范代碼,假設(shè)c:/temp/large_file.dat文件有130MB大小()//每次讀入10MB字節(jié),并且對(duì)文件中每個(gè)字節(jié)進(jìn)行操作,由于可以使用異步操作所以可以在下一次讀入數(shù)據(jù)的同時(shí)進(jìn)行計(jì)算void ReadM1(void){	HANDLE hFile = CreateFile("c://temp//large_file.dat",GENERIC_READ,0,				NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED|FILE_ATTRIBUTE_NORMAL,NULL);	if( INVALID_HANDLE_VALUE != hFile )	{		HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,"read_event");		BYTE *pbRead = new BYTE[1024*1024*10];//10MB字節(jié)		BYTE *pbBuf = new BYTE[1024*1024*10];		DWORD dwRead,dwCount=0;		OVERLAPPED overlap;		overlap.Offset = 0;		overlap.OffsetHigh =0;		overlap.hEvent = hEvent;				DWORD dwBegin= GetTickCount();//記錄開始時(shí)間		ReadFile(hFile,pbRead,1024*1024*10,&dwRead,&overlap);		{//開始計(jì)算			for(int i=1;i<13;i++)			{				printf("M1 i=%d/n",i);				WaitForSingleObject(hEvent,INFINITE);//等待上一次完成				memcpy(pbBuf,pbRead,1024*1024*10);				overlap.Offset = i * (1024*1024*10);				overlap.OffsetHigh =0;				overlap.hEvent = hEvent;				ReadFile(hFile,pbRead,1024*1024*10,&dwRead,&overlap);				//在文件進(jìn)行讀的同時(shí)進(jìn)行計(jì)算				DoDataDeal(pbBuf,1024*1024*10);			}			WaitForSingleObject(hEvent,INFINITE);//等待最后一次完成			memcpy(pbBuf,pbRead,1024*1024*10);			//數(shù)據(jù)處理			DoDataDeal(pbBuf,1024*1024*10);		}//結(jié)束計(jì)算		printf("耗時(shí) %d/n",GetTickCount()-dwBegin);		//操作完成		CloseHandle(hEvent);		CloseHandle(hFile);		delete pbRead;		delete pbBuf;	}}//下面是上面功能的文件同步讀版本void ReadM2(void){	HANDLE hFile = CreateFile("c://temp//large_file.dat",GENERIC_READ,0,				NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);	if( INVALID_HANDLE_VALUE != hFile )	{		DWORD dwRead,dwCount=0;		BYTE *pbRead = new BYTE[1024*1024*10];//10MB字節(jié)		BYTE *pbBuf = new BYTE[1024*1024*10];//10MB字節(jié)				DWORD dwBegin= GetTickCount();//記錄開始時(shí)間		for(int i=0;i<13;i++)		{			printf("M2 i=%d/n",i);			if(!ReadFile(hFile,pbRead,1024*1024*10,&dwRead,NULL))			{				printf("error read");				break;			}			memcpy(pbBuf,pbRead,1024*1024*10);			//計(jì)算			DoDataDeal(pbBuf,1024*1024*10);		}		printf("耗時(shí) %d/n",GetTickCount()-dwBegin);		//操作完成		CloseHandle(hFile);		delete pbRead;		delete pbBuf;	}}在文件的異步讀寫中,如果ReadFile/WriteFile返回FALSE,則需要通過(guò)LastError來(lái)進(jìn)一步確認(rèn)是否發(fā)生錯(cuò)誤,例如下面的錯(cuò)誤檢測(cè)代碼:
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead,     &gOverlapped) ; if (!bResult)     switch (dwError = GetLastError())     {         case ERROR_HANDLE_EOF:         {           //到達(dá)文件尾        }          case ERROR_IO_PENDING:         {             //正在進(jìn)行異步操作        } // end case      } // end switch } // end if 此外可以通過(guò)GetOverlappedResult函數(shù)來(lái)得到異步函數(shù)的執(zhí)行情況BOOL GetOverlappedResult(  HANDLE hFile,                       // handle to file, pipe, or device  LPOVERLAPPED lpOverlapped,          // overlapped structure  LPDWORD lpNumberOfBytesTransferred, // bytes transferred  BOOL bWait                          // wait option);如果函數(shù)調(diào)用返回FALSE則可以用GetLastError來(lái)得到錯(cuò)誤,如果返回成功則可以通過(guò)lpNumberOfBytesTransferred參數(shù)來(lái)確定當(dāng)前有多少數(shù)據(jù)已經(jīng)被讀或?qū)憽pOverlapped參數(shù)必須與調(diào)用ReadFile或WriteFile時(shí)使用同一個(gè)數(shù)據(jù)區(qū)。最后一個(gè)參數(shù)bWait表明是否等待異步操作結(jié)束時(shí)才返回,如果設(shè)置為TRUE就可以等待文件讀寫完成時(shí)返回,否則就會(huì)馬上返回,利用這個(gè)特點(diǎn)可以利用它來(lái)等待異步文件操作的結(jié)束(就如同等待事件變?yōu)橛行盘?hào)狀態(tài)一樣起到相同的作用)。

在上面的例子中沒(méi)有過(guò)多的進(jìn)行錯(cuò)誤檢查,如果大家有興趣可以自己運(yùn)行一下這個(gè)例子,看看異步文件讀寫對(duì)性能的影響。在我自己的計(jì)算機(jī)PII 450 IBM 30GB硬盤上同步讀比異步讀慢了大約10%左右,這主要時(shí)因?yàn)閿?shù)據(jù)處理時(shí)間我設(shè)置為兩秒鐘,如果設(shè)置得足夠長(zhǎng),會(huì)顯示出異步和同步處理時(shí)的差異極限。此外由于磁盤緩存得作用也會(huì)影響結(jié)果,所以如果讀入的數(shù)據(jù)量更大將會(huì)產(chǎn)生更明顯的差異,這是因?yàn)殡m然異步讀寫會(huì)在調(diào)用等待函數(shù)上也會(huì)耗費(fèi)一些時(shí)間,所以如果數(shù)據(jù)量小就無(wú)法分辨出差異。

請(qǐng)記住OVERLAPPED參數(shù)在文件操作執(zhí)行完以前不要手工修改結(jié)構(gòu)內(nèi)的值,因?yàn)橄到y(tǒng)會(huì)使用結(jié)構(gòu)中的數(shù)據(jù)。

對(duì)于WriteFile操作也可以用相同方法,在WriteFile中磁盤操作將耗費(fèi)更多的時(shí)間,所以使用異步寫更能體現(xiàn)優(yōu)勢(shì),你可以將這個(gè)例子改為磁盤寫后自己測(cè)試一下。

下載利用ReadFile進(jìn)行異步文件讀的示范代碼

第二種方法,利用ReadFileEx/WriteFileEx,這對(duì)函數(shù)使用回調(diào)函數(shù)來(lái)進(jìn)行讀寫完成的通知。

BOOL ReadFileEx(  HANDLE hFile,                                       // handle to file  LPVOID lpBuffer,                                    // data buffer  DWORD nNumberOfBytesToRead,                         // number of bytes to read  LPOVERLAPPED lpOverlapped,                          // offset  LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // completion routine);hFile為文件句柄。lpBuffer指明了寫入數(shù)據(jù)的內(nèi)存區(qū)指針。nNumberOfBytesToRead為要求讀入的數(shù)據(jù)字節(jié)數(shù)。lpOverlapped為一個(gè)OVERLAPPED的結(jié)構(gòu),這個(gè)結(jié)構(gòu)hEvent字段將被系統(tǒng)忽略,但是通過(guò)Offset和OffsetHigh字段來(lái)表明開始讀文件的位置。lpCompletionRoutine為一個(gè)通知用的回調(diào)函數(shù)。函數(shù)的最后一個(gè)參數(shù)指明了一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)稱為一個(gè)告警函數(shù)。函數(shù)必須具有這樣的原型:
VOID CALLBACK FileIOCompletionRoutine(  DWORD dwErrorCode,                // completion code  DWORD dwNumberOfBytesTransfered,  // number of bytes transferred  LPOVERLAPPED lpOverlapped         // I/O information buffer);dwErrorCode為錯(cuò)誤代碼,如果為0表示正確,為ERROR_HANDLE_EOF表示到達(dá)文件的末尾。dwNumberOfBytesTransfered為成功傳送的字節(jié)數(shù),如果發(fā)生錯(cuò)誤,這個(gè)值為0。lpOverlapped為一個(gè)OVERLAPPED的結(jié)構(gòu),這個(gè)結(jié)構(gòu)必須與調(diào)用ReadFileEx時(shí)指向相同的數(shù)據(jù)區(qū),并且在調(diào)用ReadFileEx后不能手工更改這個(gè)結(jié)構(gòu)中的字段。

那么如何檢測(cè)回調(diào)函數(shù)已經(jīng)被調(diào)用了(文件操作已經(jīng)完成),你可以設(shè)置一個(gè)全局的同步量來(lái)進(jìn)行通知,但是系統(tǒng)提供了其他簡(jiǎn)便的方法供開發(fā)者使用,這就是SleepEx WaitForMultipleObjectsEx 和WaitForSingleObjectEx。

當(dāng)線程調(diào)用ReadFileEx或WriteFileEx時(shí),提供了一個(gè)告警函數(shù),這個(gè)告警函數(shù)會(huì)被放入一個(gè)隊(duì)列,當(dāng)操作完成時(shí)操作系統(tǒng)會(huì)從隊(duì)列中取出這些函數(shù)進(jìn)行調(diào)用。所以對(duì)于屬于本進(jìn)程內(nèi)部所產(chǎn)生的需要等待被調(diào)用的告警函數(shù)來(lái)說(shuō)可以直接使用SleepEx對(duì)當(dāng)前線程進(jìn)行休眠并等待當(dāng)前提交所有的告警函數(shù)被執(zhí)行。如果希望等待指定文件操作上的告警函數(shù)被調(diào)用你可以使用WaitForMultipleObjectsEx或WaitForSingleObjectEx。這三個(gè)函數(shù)的原型為:

DWORD SleepEx(  DWORD dwMilliseconds,  // time-out interval  BOOL bAlertable        // early completion option);DWORD WaitForSingleObjectEx(  HANDLE hHandle,        // handle to object  DWORD dwMilliseconds,  // time-out interval  BOOL bAlertable        // alertable option);DWORD WaitForMultipleObjectsEx(  DWORD nCount,             // number of handles in array  CONST HANDLE *lpHandles,  // object-handle array  BOOL fWaitAll,            // wait option  DWORD dwMilliseconds,     // time-out interval  BOOL bAlertable           // alertable option);這三個(gè)函數(shù)和Sleep WaitForSingleObject WaitForMultipleObjects的差別就在于多了最后一個(gè)參數(shù)bAlertable,這個(gè)參數(shù)需要設(shè)置為TRUE表明等待文件異步操作的完成。通過(guò)檢測(cè)函數(shù)返回值可以得知文件操作是否完成,例如下面的代碼:
	ReadFileEx(hFile,pbRead,1024*1024*50,&overlap,MyIORoutine);	while(WAIT_IO_COMPLETION != SleepEx(1,TRUE) )//檢測(cè)文件操作是否完成	//while (WaitForSingleObjectEx(hFile,1,TRUE) != WAIT_OBJECT_0 ) 	//在這里WaitForSingleObjectEx和SleepEx具有相同作用	{		DoSomething();	}對(duì)于SleepEx來(lái)說(shuō)如果返回WAIT_IO_COMPLETION則表示異步操作完成,而對(duì)于文件對(duì)象來(lái)說(shuō)如果異步操作完成文件對(duì)象就會(huì)變?yōu)橛行盘?hào)狀態(tài)。下面的例子是一個(gè)利用告警回調(diào)函數(shù)實(shí)現(xiàn)的文件異步讀寫。
VOID CALLBACK MyIORoutine(  DWORD dwErrorCode,                // completion code  DWORD dwNumberOfBytesTransfered,  // number of bytes transferred  LPOVERLAPPED lpOverlapped         // I/O information buffer){//定義一個(gè)簡(jiǎn)單的回調(diào)函數(shù)	printf("文件讀完成/n");}void DoSomething(void){	printf("current time %d/n",GetTickCount());	Sleep(2000);//假設(shè)耗時(shí)的操作需要兩秒鐘}//下面是使用異步讀的示范代碼,假設(shè)c:/temp/large_file.dat文件有130MB大小()//一次性讀入50MB字節(jié),在讀入的過(guò)程中進(jìn)行一些其他操作void ReadM(void){	HANDLE hFile = CreateFile("c://temp//large_file.dat",GENERIC_READ,0,				NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED|FILE_ATTRIBUTE_NORMAL,NULL);	if( INVALID_HANDLE_VALUE != hFile )	{		BYTE *pbRead = new BYTE[1024*1024*50];//50MB字節(jié)		OVERLAPPED overlap;		overlap.Offset = 0;		overlap.OffsetHigh =0;		overlap.hEvent = NULL; //使用告警函數(shù)時(shí)無(wú)需要使用事件				DWORD dwBegin= GetTickCount();//記錄開始時(shí)間		printf("begin time %d/n",dwBegin);		ReadFileEx(hFile,pbRead,1024*1024*50,&overlap,MyIORoutine);		while(WAIT_IO_COMPLETION != SleepEx(1,TRUE) )//檢測(cè)文件操作是否完成		//while (WaitForSingleObjectEx(hFile,1,TRUE) != WAIT_OBJECT_0 ) 		//在這里WaitForSingleObjectEx和SleepEx具有相同作用		{			DoSomething();//在文件讀的執(zhí)行過(guò)程中進(jìn)行其他操作		}		printf("耗時(shí) %d/n",GetTickCount()-dwBegin);		//操作完成		CloseHandle(hFile);		delete pbRead;	}}

WriteFileEx的用法與ReadFileEx的用法是類似的。

下載利用ReadFileEx進(jìn)行異步文件讀的示范代碼

在磁盤操作中磁盤寫比讀需要花更多的時(shí)間,并且大文件的異步寫可以更加有效的提高CPU利用率。但是異步操作會(huì)給開發(fā)和調(diào)試帶來(lái)一些麻煩,所以我建議除非在非常必要(性能要求非常高,文件非常大)的情況下才使用異步的磁盤讀寫。再提一點(diǎn),對(duì)于磁盤文件的異步操作的方式同樣可以用于上章所講的命名管道,或者是串口的異步操作。

文件加鎖時(shí)在打開文件后對(duì)文件的某個(gè)區(qū)域加鎖,加鎖后可以防止其他進(jìn)程對(duì)該區(qū)域數(shù)據(jù)進(jìn)行讀取。相關(guān)的函數(shù)為:

BOOL LockFile(  HANDLE hFile,                   // 文件句柄  DWORD dwFileOffsetLow,          // 文件加鎖開始位置低32位  DWORD dwFileOffsetHigh,         // 文件加鎖開始位置高32位  DWORD nNumberOfBytesToLockLow,  // 區(qū)域長(zhǎng)度低32位  DWORD nNumberOfBytesToLockHigh  // 區(qū)域長(zhǎng)度高32位);BOOL UnlockFile(  HANDLE hFile,                    // 文件句柄  DWORD dwFileOffsetLow,          // 文件解鎖開始位置低32位  DWORD dwFileOffsetHigh,         // 文件解鎖開始位置高32位  DWORD nNumberOfBytesToLockLow,  // 區(qū)域長(zhǎng)度低32位  DWORD nNumberOfBytesToLockHigh  // 區(qū)域長(zhǎng)度高32位);在文件加鎖和解鎖上需要有對(duì)應(yīng)關(guān)系,這種對(duì)應(yīng)關(guān)系就是對(duì)A區(qū)域加鎖后必須對(duì)A區(qū)域解鎖后才可以對(duì)其他區(qū)域解鎖,而且必須是一對(duì)一的關(guān)系,也就是說(shuō)調(diào)用一次對(duì)A區(qū)域的加鎖函數(shù)就必須調(diào)用一次對(duì)A區(qū)域的解鎖函數(shù),而不能對(duì)一個(gè)區(qū)域加鎖后分次對(duì)該區(qū)域的不同部分解鎖。

在MFC中對(duì)文件操作進(jìn)行了封裝,CFile中封裝了各種文件操作。在CFile中常用的成員函數(shù)有以下這些:

CFile( LPCTSTR lpszFileName, UINT nOpenFlags ); //打開文件virtual BOOL Open( LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL ); //打開文件uOpenFlags為打開文件時(shí)的參數(shù),可以取的以下值的組合:CFile::modeRead / CFile::modeReadWrite / CFile::modeWrite 讀寫模式CFile::modeCreate 創(chuàng)建文件CFile::shareDenyNone / CFile::shareDenyRead / CFile::shareDenyWrite 共享設(shè)置CFile::typeText / CFile::typeBinary 以文本形式還時(shí)二進(jìn)制形式打開文件virtual void Close( ); //關(guān)閉文件virtual UINT Read( void* lpBuf, UINT nCount ); //讀文件virtual void Write( const void* lpBuf, UINT nCount ); // 寫文件virtual LONG Seek( LONG lOff, UINT nFrom ); //設(shè)置文件指針void SeekToBegin( );//移動(dòng)文件指針到文件頭DWORD SeekToEnd( );//移動(dòng)文件指針到文件尾virtual void LockRange( DWORD dwPos, DWORD dwCount ); //鎖定文件virtual void UnlockRange( DWORD dwPos, DWORD dwCount ); //解鎖文件

CStdioFile是CFile的派生類,主要是完成對(duì)文本文件的操作,它只有兩個(gè)成員函數(shù):

BOOL ReadString(CString& rString); //讀入文件中一行void WriteString( LPCTSTR lpsz );//將字符串作為一行寫入文件
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 城固县| 蒲城县| 尉氏县| 芜湖市| 阿拉善左旗| 礼泉县| 永定县| 河南省| 宁海县| 玉林市| 奈曼旗| 高邑县| 拜城县| 临武县| 济源市| 石台县| 永靖县| 上犹县| 红河县| 永善县| 曲阳县| 吉水县| 长汀县| 四子王旗| 玉林市| 光泽县| 夏津县| 宁波市| 九江市| 金湖县| 徐水县| 普安县| 温州市| 波密县| 栖霞市| 北海市| 德保县| 汶上县| 临安市| 贺兰县| 台江县|