I believe, the best option in your case is using memory-mapped files. CreateFileMapping and MapViewOfFile will help you with this.
Below is a simple example of working with memory mapped files in Windows. I omitted error checking code and simplified the task to replacing the random string's characters with '?'. This was done intentionally to outline the main aspects only:
1) Create a memory-mapped file (CreateFile -> CreateFileMapping-> MapViewOfFile)
2) Process it as it was just a memory block. Yes, you would have to scan if from the beginning if you need to process in line mode but mmapping it would be the fastest approach as of my belief.
Important note: the real life task may require the original file to reduce or expand. It's quite easy to reduce it -- just memmove the respective portion back and truncate the file on close. Expanding would require more tricky technics.
3) Don't forget to release the resources with UnmapViewOfFile/CloseHandle.
#include "stdafx.h"
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR fileName[] = _T("SomeHugeFile.dat");
HANDLE hFile = CreateFile(
fileName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (!hFile) {
// Process the error
}
DWORD fileSize = GetFileSize(hFile, NULL);
if (!fileSize) {
// Check if it's an actual errro with GetLastError
// and process accordingly if so
}
HANDLE hMemMappedFile = CreateFileMapping(
hFile,
NULL,
PAGE_READWRITE,
0,
0,
NULL
);
if (!hMemMappedFile) {
// Process the error
}
LPVOID mappedMemory = MapViewOfFile(
hMemMappedFile,
FILE_MAP_ALL_ACCESS,
0,
0,
0 // To the end of the file
);
DWORD lineToDelete = 3; // Some random line number
// Assuming the file is ASCII and with Unix line endings
char *mappedMemoryStart = (char *)mappedMemory;
char *mappedMemoryEnd = mappedMemoryStart + fileSize;
char *lineStart = NULL;
char *lineEnd = NULL;
// Find the line start:
DWORD lineNumber = 0;
for (lineStart = (char *)mappedMemory; lineStart < mappedMemoryEnd; lineStart++) {
if (*lineStart == '\n') {
lineNumber++;
if (lineNumber == lineToDelete) {
lineStart++;
break;
}
}
}
if (lineStart >= mappedMemoryEnd) {
// Error: has gone beyond file end
}
for (lineEnd = lineStart; lineEnd < mappedMemoryEnd; lineEnd++) {
if (*lineEnd == '\n') {
break;
}
}
// Now mangle the found line:
while (lineStart < lineEnd) {
*lineStart = '?';
lineStart++;
}
UnmapViewOfFile(mappedMemory);
CloseHandle(hMemMappedFile);
CloseHandle(hFile);
return 0;
}