如何通过WinAPI的CreateFile()和WriteFile()在文件开头追加数据?
实现WinAPI将数据追加到文件开头的解决方案
方法一:内存中转法(适合小文件)
直接读取原文件内容到内存,先写入新数据,再追加原内容,步骤简单高效:
- 以读写权限打开目标文件(不存在则创建)
- 读取原文件全部内容到内存
- 将文件指针移至开头,写入新数据
- 接着写入原文件内容
- 清理资源
代码示例:
#include <windows.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { // 打开目标文件,支持读写,不存在则创建 HANDLE hFile = CreateFile( L"target.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) { printf("打开文件失败,错误码:%d\n", GetLastError()); return 1; } DWORD fileSize = GetFileSize(hFile, NULL); char* pOldContent = NULL; DWORD bytesRead = 0; // 文件非空时读取原内容 if (fileSize != 0 && fileSize != INVALID_FILE_SIZE) { pOldContent = (char*)malloc(fileSize); if (!pOldContent) { printf("内存分配失败\n"); CloseHandle(hFile); return 1; } if (!ReadFile(hFile, pOldContent, fileSize, &bytesRead, NULL)) { printf("读取原文件失败,错误码:%d\n", GetLastError()); free(pOldContent); CloseHandle(hFile); return 1; } } // 定位到文件开头,写入新数据 SetFilePointer(hFile, 0, NULL, FILE_BEGIN); const char* newData = "这是要追加到开头的新内容\n"; DWORD bytesWritten; if (!WriteFile(hFile, newData, strlen(newData), &bytesWritten, NULL)) { printf("写入新数据失败,错误码:%d\n", GetLastError()); if (pOldContent) free(pOldContent); CloseHandle(hFile); return 1; } // 写入原文件内容(如果存在) if (pOldContent && bytesRead > 0) { if (!WriteFile(hFile, pOldContent, bytesRead, &bytesWritten, NULL)) { printf("写入原内容失败,错误码:%d\n", GetLastError()); } } // 清理资源 if (pOldContent) free(pOldContent); CloseHandle(hFile); return 0; }
方法二:临时文件中转法(适合大文件)
避免一次性读取大文件占用过多内存,通过临时文件先写入新数据,再追加原文件内容,最后替换原文件:
- 创建临时文件
- 写入新数据到临时文件
- 分块读取原文件内容并追加到临时文件
- 删除原文件,将临时文件重命名为原文件名
代码示例:
#include <windows.h> #include <stdio.h> #include <string.h> int main() { WCHAR tempPath[MAX_PATH]; WCHAR tempFileName[MAX_PATH]; // 获取临时目录并生成临时文件名 if (!GetTempPath(MAX_PATH, tempPath) || !GetTempFileName(tempPath, L"APP", 0, tempFileName)) { printf("创建临时文件失败,错误码:%d\n", GetLastError()); return 1; } // 打开临时文件用于写入 HANDLE hTempFile = CreateFile( tempFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (hTempFile == INVALID_HANDLE_VALUE) { printf("打开临时文件失败,错误码:%d\n", GetLastError()); return 1; } // 写入新数据到临时文件 const char* newData = "这是追加到开头的大文件新内容\n"; DWORD bytesWritten; if (!WriteFile(hTempFile, newData, strlen(newData), &bytesWritten, NULL)) { printf("写入新数据到临时文件失败,错误码:%d\n", GetLastError()); CloseHandle(hTempFile); DeleteFile(tempFileName); return 1; } // 打开原文件读取内容 HANDLE hOldFile = CreateFile( L"target.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hOldFile != INVALID_HANDLE_VALUE) { char buffer[4096]; DWORD bytesRead; // 分块读取原文件并写入临时文件 while (ReadFile(hOldFile, buffer, sizeof(buffer), &bytesRead, NULL) && bytesRead > 0) { WriteFile(hTempFile, buffer, bytesRead, &bytesWritten, NULL); } CloseHandle(hOldFile); } CloseHandle(hTempFile); // 替换原文件:先删除原文件,再重命名临时文件 if (!DeleteFile(L"target.txt")) { printf("删除原文件失败,错误码:%d\n", GetLastError()); DeleteFile(tempFileName); return 1; } if (!MoveFile(tempFileName, L"target.txt")) { printf("重命名临时文件失败,错误码:%d\n", GetLastError()); DeleteFile(tempFileName); return 1; } return 0; }
关键说明
- 不能依赖FILE_APPEND_DATA标志:该标志的核心作用是强制每次写入自动定位到文件末尾,要实现开头追加必须放弃这个标志,改用
GENERIC_READ | GENERIC_WRITE权限手动控制写入位置。 - 小文件用内存中转更高效,大文件推荐临时文件法,避免内存溢出。
- 代码中需注意错误处理,实际使用时可根据场景补充更完善的异常判断逻辑。
内容的提问来源于stack exchange,提问作者Vinay Khatri
相关产品推荐
相关产品推荐

