AceInfinity
Emeritus, Contributor
Code:
[NO-PARSE]#ifdef _MSC_VER
# pragma warning(disable: 4996)
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#ifdef __MINGW32__
# define LONGLONG_FMT "%I64d"
#else
# define LONGLONG_FMT "%lld"
#endif
#define PAGE_SIZE 4096
int main(void)
{
DWORD i;
BOOL bSuccess = FALSE;
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hMapFile = NULL;
LONGLONG lNullBytes = 0;
DWORD dwOffset = 0;
const TCHAR *lpcFilepath = TEXT("file_small.bin");
const DWORD dwDataSize = PAGE_SIZE;
/* Open file for read/write perissions with exclusive access for compatibility with
PAGE_READWRITE page protection of the file mapping object to be created */
hFile = CreateFile(lpcFilepath, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
_ftprintf(stderr, TEXT("ERROR: Failed to open file '%s': 0x%lx\n"), lpcFilepath, GetLastError());
goto cleanup;
}
/* Get filesize */
LARGE_INTEGER liFilesize;
if (!GetFileSizeEx(hFile, &liFilesize))
{
_ftprintf(stderr, TEXT("ERROR: Could not retrieve filesize: 0x%lx\n"), GetLastError());
goto cleanup;
}
if (liFilesize.QuadPart == 0)
{
_ftprintf(stderr, TEXT("ERROR: Filesize is 0 bytes\n"));
goto cleanup;
}
LONGLONG lFilesizeUnit = liFilesize.QuadPart;
const TCHAR *lpcFilesizeSuffix = TEXT("bytes");
if (lFilesizeUnit > 1024)
{
lpcFilesizeSuffix = TEXT("Kb");
lFilesizeUnit /= 1024;
}
_tprintf(TEXT("Filesize: " LONGLONG_FMT " %s\n"), lFilesizeUnit, lpcFilesizeSuffix);
/* Create a file mapping object for the file */
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, liFilesize.u.HighPart, liFilesize.u.LowPart, NULL);
if (hMapFile == NULL)
{
_ftprintf(stderr, TEXT("ERROR: Failed to create file mapping: 0x%lx\n"), GetLastError());
goto cleanup;
}
/* Obtain system allocation granularity */
SYSTEM_INFO sysInfo;
GetNativeSystemInfo(&sysInfo);
DWORD dwAllocGranularity = sysInfo.dwAllocationGranularity;
_tprintf(TEXT("Allocation Granularity: %ldK\n"), dwAllocGranularity / 1024);
do
{
/* File offset must be a multiple of system allocation granularity */
LARGE_INTEGER liFileMapViewOffset;
liFileMapViewOffset.QuadPart = (dwOffset / dwAllocGranularity) * dwAllocGranularity;
/* _tprintf(TEXT("File mapping view offset: " LONGLONG_FMT " bytes\n"), liFileMapViewOffset.QuadPart); */
/* Calculate the size of the file mapping view */
SIZE_T dwFileMapViewSize = (dwOffset % dwAllocGranularity) + dwDataSize;
if (dwFileMapViewSize > (liFilesize.QuadPart - liFileMapViewOffset.QuadPart))
{
dwFileMapViewSize = (SIZE_T)(liFilesize.QuadPart - liFileMapViewOffset.QuadPart);
}
/* _tprintf(TEXT("File mapping view size: %ld bytes\n"), dwFileMapViewSize); */
/* The bytes we want to read aren't always at the beginning of the mapped view */
LONGLONG lViewOffset;
lViewOffset = dwOffset - liFileMapViewOffset.QuadPart;
/* _tprintf(TEXT("Data offset from view: " LONGLONG_FMT " bytes\n"), lViewOffset); */
/* Map view of file and obtain pointer to base address of the region mapped in memory */
LPVOID lpMapAddress = MapViewOfFile(hMapFile,
FILE_MAP_READ,
liFileMapViewOffset.u.HighPart,
liFileMapViewOffset.u.LowPart,
dwFileMapViewSize);
if (lpMapAddress == NULL)
{
_ftprintf(stderr, TEXT("ERROR: MapViewOfFile failed: 0x%lx\n"), GetLastError());
goto cleanup;
}
/* Calculate the offset pointer to data */
PBYTE pBytes = (PBYTE)lpMapAddress + lViewOffset;
LONGLONG lBytesTotal = liFilesize.QuadPart - liFileMapViewOffset.QuadPart;
for (i = 0; i < lBytesTotal; ++i)
{
/*_tprintf(TEXT("%02X "), *(pBytes + i));*/
if (!*(pBytes + i)) ++lNullBytes;
}
/* _tprintf(TEXT("\n")); */
/* Unmap view of file */
if (!UnmapViewOfFile(lpMapAddress))
{
_ftprintf(stderr, TEXT("ERROR: UnmapViewOfFile failed: 0x%lx\n"), GetLastError());
}
dwOffset += dwDataSize;
}
while (dwOffset < liFilesize.QuadPart);
bSuccess = TRUE;
cleanup:
/* Close file mapping object HANDLE */
if (hMapFile != NULL)
{
bSuccess &= CloseHandle(hMapFile);
if (!bSuccess)
{
_ftprintf(stderr, TEXT("ERROR: Failed to close HANDLE to file mapping object: 0x%lx\n"), GetLastError());
}
}
/* Close file HANDLE */
if (hFile != INVALID_HANDLE_VALUE)
{
bSuccess &= CloseHandle(hFile);
if (!bSuccess)
{
_ftprintf(stderr, TEXT("ERROR: Failed to close HANDLE to file: 0x%lx\n"), GetLastError());
}
}
if (bSuccess)
{
_tprintf(TEXT("Null byte count: " LONGLONG_FMT "\n"), lNullBytes);
}
_tprintf(TEXT("DONE!\n"));
return bSuccess;
}[/NO-PARSE]
Here's some code I wrote a couple days ago to demonstrate efficiently reading files on Windows by mapping views to the file into memory from a mapping object.
It's pretty basic -- I can read a ~2.5 Gb file in about 5 seconds. Performing other things during the read is obviously going to increase that timeframe a little.
^ For this test I just took an ISO/Image for Windows 7 installation that I had on a USB. It reads through the file and counts null-bytes.
:thumbsup2: