需分割巨大SQL文件,傳統讀寫方式過慢。採用內存映射文件技術,將文件直接映射至進程地址空間,避免用戶態/內核態重複拷貝,速度大幅提升。當前版本支援最大3GB文件,規劃64位版支援16EB。
用法: SplitFile -f <源文件> -s <分塊大小KB> [-h] 選項: -f 指定待分割文件路徑 -s 指定每塊大小(單位:KB) -h 顯示幫助信息 示例: SplitFile -f data.sql -s 1024
typedef struct FILEINFO {
LPSTR lpFileName;
DWORD dwFileLowSize;
DWORD dwFileHighSize;
DWORD dwFileSize;
DWORD dwPartNum;
} FILEINFO;
int main(int argc, char *argv[]) {
HANDLE hInFile = INVALID_HANDLE_VALUE, hInMap;
FILEINFO fi = {0};
BOOL bHelp = FALSE;
DWORD dwPartSize = 0;
// 參數解析
for (int i = 0; i < argc; i++) {
if (argc == 1) { bHelp = TRUE; continue; }
LPSTR lpChkCmd = argv[i], lpValue = argv[i+1];
if (lstrcmp(lpChkCmd, "-f") == 0) fi.lpFileName = lpValue;
else if (lstrcmp(lpChkCmd, "-s") == 0) dwPartSize = atol(lpValue) * 1024;
else if (lstrcmp(lpChkCmd, "-h") == 0) bHelp = TRUE;
}
if (bHelp) { PrintUsage(argv[0]); exit(1); }
// 打開源文件並創建映射
hInFile = CreateFile(fi.lpFileName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hInFile == INVALID_HANDLE_VALUE) { PrintError("打開文件失敗"); return 0; }
fi.dwFileLowSize = GetFileSize(hInFile, &fi.dwFileHighSize);
fi.dwFileSize = fi.dwFileLowSize; // 當前僅支援低32位
hInMap = CreateFileMapping(hInFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (!hInMap) { PrintError("創建源文件映射失敗"); CloseHandle(hInFile); return 0; }
// 計算分塊數
fi.dwPartNum = fi.dwFileSize / dwPartSize;
if (fi.dwFileSize % dwPartSize) fi.dwPartNum++;
printf("文件大小:%u KB 分塊數:%u\n", fi.dwFileSize/1024, fi.dwPartNum);
system("pause");
DWORD dwBegin = GetTickCount(), dwCurAddr = 0;
for (int index = 0; index < fi.dwPartNum; index++) {
DWORD dwCurSize = min(dwPartSize, fi.dwFileSize - dwCurAddr);
// 映射源文件當前視圖
LPVOID lpInMapContext = MapViewOfFile(hInMap, FILE_MAP_READ|FILE_MAP_WRITE,
0, dwCurAddr, dwCurSize);
if (!lpInMapContext) { PrintError("創建源文件視圖失敗"); Cleanup(); return 0; }
// 創建目標文件及映射
char cIndex[4]; itoa(index+1, cIndex, 10);
HANDLE hOutFile = CreateFile(cIndex, GENERIC_ALL, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hOutMap = CreateFileMapping(hOutFile, NULL, PAGE_READWRITE, 0, dwCurSize, NULL);
LPVOID lpOutMapContext = MapViewOfFile(hOutMap, FILE_MAP_WRITE, 0, 0, 0);
// 內存級拷貝(極速)
CopyMemory(lpOutMapContext, lpInMapContext, dwCurSize);
printf("[MSG]分塊%d完成.\n", index+1);
// 釋放當前塊資源
UnmapViewOfFile(lpInMapContext);
UnmapViewOfFile(lpOutMapContext);
CloseHandle(hOutMap); CloseHandle(hOutFile);
dwCurAddr += dwCurSize;
}
CloseHandle(hInMap); CloseHandle(hInFile);
printf("用時:%u毫秒\n", GetTickCount() - dwBegin);
return 1;
}
代碼為快速Demo風格,生產環境建議加強異常處理、進度顯示、校驗碼驗證等功能。
本文出自「About:Blank H4cking」博客,轉載請保留出處。