Я пытаюсь вычислить (надеюсь, простой) способ прочитать большой, неструктурированный файл, не нападая на край буфера. Пример здесь полезен.
Представьте, что вы пытаетесь выполнить некоторое восстановление данных с флэш-накопителя на 16 ГБ и сохранили дамп диска в 16-гигабайтный файл. Вы хотите просмотреть изображение, просматривая некоторые интересующие вас объекты. Если файл был меньше, вы могли бы прочитать все это в буфер памяти (скажем, 1 МБ) и выполнить простую проверку через буфер. Однако, поскольку он слишком велик, чтобы читать все сразу, вам нужно прочитать его в кусках. Проблема в том, что интересующий элемент может быть не совсем выровнен, чтобы попасть в один буфер 1 МБ. Другими словами, он может оказаться на краю буфера, чтобы он начинался в конце буфера во время одного чтения и заканчивался в следующем (или даже дальше).
В свое время я имел дело с этим, используя два буфера и копируя второй для первого, чтобы создать своеобразное скользящее окно, однако я предполагаю, что это должен быть достаточно распространенный сценарий, что есть лучшие существующие решения, Я искал файлы с отображением памяти, думая, что они позволяют вам читать файл, просто увеличивая индекс/указатель массива, но я оказался в той же ситуации, что и раньше, из-за ограничения размера вида карты. Я попытался найти некоторые практические примеры использования MapViewOfFile
со смещениями, но все, что я мог найти, было надуманными примерами, которые пропустили это.
Как обычно эта ситуация обрабатывается?
Если вы работаете в 64-битной среде, я бы просто использовал файлы с отображением памяти. Для процесса нет (разумного) предела памяти. Вы можете прочитать файл, даже прыгать, и ОС будет заменять память на диск и с диска.
Вот некоторые основные сведения:
http://msdn.microsoft.com/en-us/library/ms810613.aspx
И пример средства просмотра файлов здесь:
http://www.catch22.net/tuts/memory-techniques-part-1
Этот случай работает с 2.8GB файлом в x64, но сбой в win32, поскольку он не может выделить более 2 ГБ на процесс. Это очень быстро, так как он касается только первого и последнего байтов в массиве pBuf. Модификация метода для перемещения буфера и подсчета количества "нулевых" байтов работает так, как ожидалось. Вы можете наблюдать, как след памяти растет, как только он делает это, но эта память только фактически распределена.
#include "stdafx.h"
#include <string>
#include <Windows.h>
TCHAR szName[] = TEXT( pathToFile );
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hMapFile;
char* pBuf;
HANDLE file = CreateFile( szName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if ( file == NULL )
{
_tprintf(TEXT("Could not open file object (%d).\n"),
GetLastError());
return 1;
}
unsigned int length = GetFileSize(file, 0);
printf( "Length = %u\n", length );
hMapFile = CreateFileMapping( file, 0, PAGE_READONLY, 0, 0, 0 );
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"), GetLastError());
return 1;
}
pBuf = (char*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0,0, length);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError());
CloseHandle(hMapFile);
return 1;
}
printf("First Byte: 0x%02x\n", pBuf[0] );
printf("Last Byte: 0x%02x\n", pBuf[length-1] );
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}