尽管理论上说,我们能将一个16EB大小的文件映射到一个小的地址空间中,但实际上做不到。你要映射只包含一小部分文件数据的文件视图。你可以从映射文件最开头的视图开始,当完成了文件的第一块视图,你能取消它的映射并映射一块新的视图。这块新视图在文件中有更深的偏移量。重复这一过程直到你处理完整个文件。对于处理大的内的映射文件来说,处理这一过程可能并不方便,但幸运的是,大多数的文件不算大,所以这个问题并不存在。让我们一起看一个例子,一个8GB的文件和一个32位的地址空间。统计二进制文件中0的个数的处理过程如下:
__int64 Count0s(void) {
// Views must always start on a multiple
// of the allocation granularity
SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
// Open the data file.
HANDLE hFile = CreateFile(TEXT("C:\\HugeFile.Big"), GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
// Create the file-mapping object.
HANDLE hFileMapping = CreateFileMapping(hFile, NULL,
PAGE_READONLY, 0, 0, NULL);
DWORD dwFileSizeHigh;
__int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
qwFileSize += (((__int64) dwFileSizeHigh) << 32);
// We no longer need access to the file object's handle.
CloseHandle(hFile);
__int64 qwFileOffset = 0, qwNumOf0s = 0;
while (qwFileSize > 0) {
// Determine the number of bytes to be mapped in this view
DWORD dwBytesInBlock = sinf.dwAllocationGranularity;
if (qwFileSize < sinf.dwAllocationGranularity)
dwBytesInBlock = (DWORD) qwFileSize;
PBYTE pbFile = (PBYTE) MapViewOfFile(hFileMapping, FILE_MAP_READ,
(DWORD) (qwFileOffset >> 32), // Starting byte
(DWORD) (qwFileOffset & 0xFFFFFFFF), // in file
dwBytesInBlock); // # of bytes to map
Windows via C/C++, Fifth Edition by Jeffrey Richter and Christophe Nasarre
// Count the number of 0s in this block.
for (DWORD dwByte = 0; dwByte < dwBytesInBlock; dwByte++) {
if (pbFile[dwByte] == 0)
qwNumOf0s++;
}
// Unmap the view; we don't want multiple views
// in our address space.
UnmapViewOfFile(pbFile);
// Skip to the next set of bytes in the file.
qwFileOffset += dwBytesInBlock;
qwFileSize -= dwBytesInBlock;
}
CloseHandle(hFileMapping);
return(qwNumOf0s);
}
这个算法映射了64KB(分配粒度大小)或者更小的视图。同时,记住MapViewOfFile需要文件的偏移参数是分配粒度大小的倍数。在扫描0的过程中,每个视图都被映射到地址空间。在每个64KB的文件数据块被映射并扫描后,不要忘记通过关闭文件映射对象来清理空间。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。