- 获取文件的逻辑大小——GetFileSizeEx函数
函数原型:
BOOL WINAPI GetFileSizeEx( __in HANDLE hFile, __out PLARGE_INTEGER lpFileSize );
GetFileSizeEx函数的第一个参数就不多说了,hFile就是CreateFile函数返回的句柄;
第二个参数lpFileSize是一个指向64bit union的指针.
- 获取文件的物理大小——GetCompressedFileSize函数
函数原型:
DWORD WINAPI GetCompressedFileSize( __in LPCTSTR lpFileName, __out_opt LPDWORD lpFileSizeHigh );
该函数的第一个参数lpFileName,注意与GetFileSizeEx函数的差别,GetFileSizeEx的第一个参数是句柄hFile,而该函数的第一个参数是文件名lpFileName;
第二个参数lpFileSizeHigh,由于文件大小是有64bit来记录的,其中32bit的高位记录在lpFileSizeHigh指向的内容中,而32bit的低位作为函数值返回。
//一个简单示例: ULARGE_INTEGER ulFileSize; ulFileSize.LowPart = GetCompressedFileSize(TEXT("SomeFile.dat"), &ulFileSize.HighPart); // 64-bit file size is now in ulFileSize.QuadPart
同时注意区分GetFileSizeEx获取的逻辑大小和GetCompressedFileSize获取的物理大小,例如一个100KB的文件经过压缩后只占用85KB。调用GetFileSizeEx函数返回的是文件的逻辑大小,即100KB;而调用GetCompressedFileSize函数则返回的是文件占用磁盘的物理大小,即85KB。
每次用CreateFile文件时,都有一个与文件句柄对应的文件指针,在调用ReadFile和WriteFile之后,文件指针都会前移到相应的位置。
//示例1 BYTE pb[10]; DWORD dwNumBytes; HANDLE hFile = CreateFile(TEXT("MyFile.dat"), ...); // 文件指针初始化时是0 ReadFile(hFile, pb, 10, &dwNumBytes, NULL); // 读取0-9字节 ReadFile(hFile, pb, 10, &dwNumBytes, NULL); // 读取10-19字节 //示例2 BYTE pb[10]; DWORD dwNumBytes; HANDLE hFile1 = CreateFile(TEXT("MyFile.dat"), ...); // 文件指针初始化时是0 HANDLE hFile2 = CreateFile(TEXT("MyFile.dat"), ...); // 文件指针初始化时是0 //由于每个对象有自己的文件指针,所有两次读取的数据都是0-9字节。 ReadFile(hFile1, pb, 10, &dwNumBytes, NULL); // 读取0-9字节 ReadFile(hFile2, pb, 10, &dwNumBytes, NULL); // 读取0-9字节 //示例3 BYTE pb[10]; DWORD dwNumBytes; HANDLE hFile1 = CreateFile(TEXT("MyFile.dat"), ...); // Pointer set to 0 HANDLE hFile2; //调用DuplicateHandle函数后,hFile1,hFile2共享同一个内核对象, //所有无论是用hFile1作为参数还是hFile2,文件指针都会前移的。 DuplicateHandle( GetCurrentProcess(), hFile1, GetCurrentProcess(), &hFile2, 0, FALSE, DUPLICATE_SAME_ACCESS); ReadFile(hFile1, pb, 10, &dwNumBytes, NULL); // Reads bytes 0 - 9 ReadFile(hFile2, pb, 10, &dwNumBytes, NULL); // Reads bytes 10 - 19
- 文件指针定位函数——SetFilePointerEx函数
函数原型:
BOOL WINAPI SetFilePointerEx( __in HANDLE hFile, __in LARGE_INTEGER liDistanceToMove, __out_opt PLARGE_INTEGER lpNewFilePointer, __in DWORD dwMoveMethod );
第一个参数hFile就是文件句柄;
第二个参数liDistanceToMove是移动距离,如果是负数,则表示指针后退,正数则表示指针前移;
第三个参数lpNewFilePointer,在函数返回时它标示的是文件指针之前的位置。
第四个参数dwMoveMethod,指定了文件开始移动时文件位置,
Value |
Meaning |
FILE_BEGIN 0 |
The starting point is zero or the beginning of the file. If this flag is specified, then theliDistanceToMove parameter is interpreted as an unsigned value. |
FILE_CURRENT 1 |
The start point is the current value of the file pointer. |
FILE_END 2 |
The starting point is the current end-of-file position. |
- 设置文件尾函数——SetEndofFile函数
SetEndofFile函数将当前文件指针所在位置设置为文件尾部,用法简单。
- 示例:
int testFile() { HANDLE h = CreateFile(TEXT("test.txt"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == h) { cout<<"打开文件失败!"<<endl; return -1; } else { LARGE_INTEGER fileSize; TCHAR str[]=TEXT("fuck you"); SetFilePointer(h, 0, NULL, FILE_END); DWORD dwLenWritten; for(int i = 0; i < 4; ++i) WriteFile(h, str, sizeof(str), &dwLenWritten, NULL); GetFileSizeEx(h, &fileSize); cout<<fileSize.QuadPart<<endl; CloseHandle(h); } return 0; }