我相信,在您的情况下,最好的选择是使用内存映射文件。 CreateFileMapping 和 MapViewOfFile 将帮助您解决此问题。
以下是在 Windows 中使用内存映射文件的简单示例。我省略了错误检查代码并将任务简化为用“?”替换随机字符串的字符。这样做是为了仅概述主要方面:
1) 创建内存映射文件(CreateFile -> CreateFileMapping-> MapViewOfFile)
2) 处理它,因为它只是一个内存块。是的,如果您需要以行模式处理,则必须从一开始就进行扫描,但据我所知,映射它将是最快的方法。
重要提示:现实生活中的任务可能需要对原始文件进行缩小或扩大。减少它很容易——只需将相应的部分返回并在关闭时截断文件。扩展需要更复杂的技术。
3) 不要忘记使用 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;
}