汇聚知识碎片,解决技术难题,专注提供易语言源码资源,视频教程,等在线学习交流论坛
 
发新帖
楼主: 天启
查看: 1683|回复: 1

[教程] 易语言内存映射文件处理大文件

[复制链接]
天启VIP6 发表于 2020-4-23 17:17:20 | 显示全部楼层
  1. // 创建文件内核对象,其句柄保存于hFile
  2. HANDLE hFile = CreateFile(“Recv1.zip”,GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ, NULL,
  3. CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);

  4. // 创建文件映射内核对象,句柄保存于hFileMapping
  5. HANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE, 0, 0x4000000, NULL);

  6. // 释放文件内核对象
  7. CloseHandle(hFile);

  8. // 设定大小、偏移量等参数
  9. __int64 qwFileSize = 0x4000000;
  10. __int64 qwFileOffset = 0;
  11. __int64 T = 600 * sinf.dwAllocationGranularity;
  12. DWORD dwBytesInBlock = 1000 * sinf.dwAllocationGranularity;

  13. // 将文件数据映射到进程的地址空间
  14. PBYTE pbFile = (PBYTE)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,(DWORD)(qwFileOffset
  15. >>32), (DWORD)(qwFileOffset&0xFFFFFFFF), dwBytesInBlock);
  16. while(bLoop)
  17. {

  18. // 捕获事件hEvent[0]和事件hEvent[1]
  19. DWORD ret = WaitForMultipleObjects(2, hEvent, FALSE, INFINITE);
  20. ret -= WAIT_OBJECT_0;
  21. switch (ret)
  22. {

  23. // 接收数据事件触发
  24. case 0:

  25. // 从端口接收数据并保存到内存映射文件
  26. nReadLen=syio_Read(port[1], pbFile + qwFileOffset, QueueLen);
  27. qwFileOffset += nReadLen;

  28. // 当数据写满%时,为防数据溢出,需要在其后开辟一新的映射视图
  29. if (qwFileOffset > T)
  30. {
  31. T = qwFileOffset + 600 * sinf.dwAllocationGranularity;UnmapViewOfFile(pbFile);
  32. pbFile = (PBYTE)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,(DWORD)(qwFileOffset>>32),
  33. (DWORD)(qwFileOffset&0xFFFFFFFF), dwBytesInBlock);
  34. }
  35. break;

  36. // 终止事件触发
  37. case 1:
  38. bLoop = FALSE;

  39. // 从进程的地址空间撤消文件数据映像
  40. UnmapViewOfFile(pbFile);

  41. // 关闭文件映射对象
  42. CloseHandle(hFileMapping);
  43. break;
  44. }
  45. }…

  46. 在终止事件触发处理过程中如果只简单的执行UnmapViewOfFile()和CloseHandle()函数将无法正确标识文件
  47. 的实际大小,即如果开辟的内存映射文件为GB,而接收的数据只有GB,那么上述程序执行完后,保存的文
  48. 件长度仍是GB。也就是说,在处理完成后还要再次通过内存映射文件的形式将文件恢复到实际大小,下面是
  49. 实现此要求的主要代码:

  50. // 创建另外一个文件内核对象
  51. hFile2 = CreateFile(“Recv.zip”, GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ, NULL,CREAT
  52. E_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN,NULL);

  53. // 以实际数据长度创建另外一个文件映射内核对象
  54. hFileMapping2 = CreateFileMapping(hFile2,NULL, PAGE_READWRITE,0,(DWORD)(qwFileOffset&0xFFF
  55. FFFFF),NULL);

  56. // 关闭文件内核对象
  57. CloseHandle(hFile2);

  58. // 将文件数据映射到进程的地址空间
  59. pbFile2 = (PBYTE)MapViewOfFile(hFileMapping2, FILE_MAP_ALL_ACCESS, 0, 0, qwFileOffset);

  60. // 将数据从原来的内存映射文件复制到此内存映射文件
  61. memcpy(pbFile2, pbFile, qwFileOffset);
  62. file:

  63. //从进程的地址空间撤消文件数据映像
  64. UnmapViewOfFile(pbFile);
  65. UnmapViewOfFile(pbFile2);

  66. // 关闭文件映射对象
  67. CloseHandle(hFileMapping);
  68. CloseHandle(hFileMapping2);

  69. // 删除临时文件
  70. DeleteFile(“Recv1.zip”);
复制代码


iYuYan 发表于 2020-4-23 18:55:47 | 显示全部楼层
好东西
快速回复 返回顶部 返回列表