Windows核心编程系列文章仅作为实验报告和Windows编程学习参考,不作为任何技术文章,还望大佬们勿喷。

1. 实验名称

文件编程

2. 实验环境

  1. VC6++和VS2015
  2. Windows 7

3. 实验目的

  1. 掌握文件目录管理、磁盘文件读取
  2. 掌握内存映射文件基本概念,实现步骤和相关api函数应用,采用内存映射文件进行数据共享和文件分割

4. 实验内容、步骤及结果

1. 实验内容

(1). 在给得课件代码基础上,采用内存映射文件实现两个进程数据共享,写进程,通过键盘输入数据,然后写入数据。然后读进程,则把写进程写入内存的数据读取出来。
(2). 采用内存文件映射,对一个大文件(大于2G的文件)进行读,并把该文件分割成多个子文件,保存在磁盘中。

2. 实验步骤

  1. 采用内存映射,实现进程数据共享。
  1. #include <Windows.h>
  2. #include <stdio.h>
  3. void main()
  4. {
  5. TCHAR szName[] = TEXT("2015122075"); // 内存映射对象的名称
  6. char szData[100]; // 共享内存中的数据
  7. LPVOID pBuffer; // 共享内存指针
  8. HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,0,szName);
  9. if (hMap != NULL)
  10. {
  11. pBuffer = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); // 打开成功
  12. printf("读到的共享内存中的数据是:%s \n", (char *)pBuffer);
  13. }
  14. else
  15. {
  16. printf("请输入数据: "); //打开失败
  17. scanf("%s", szData);
  18. fflush(stdin);
  19. hMap = CreateFileMapping(INVALID_HANDLE_VALUE,
  20. NULL,
  21. PAGE_READWRITE,
  22. 0,
  23. strlen(szData) + 1,
  24. szName
  25. );
  26. pBuffer = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); //映射对象的一个视图,得到指向共享内存的指针,设置里面的数据。
  27. strcpy((char *)pBuffer,szData);
  28. printf("写入共享内存的数据:%s \n", (char *)pBuffer);
  29. }
  30. getchar(); // 解除文件映射,关闭内存映射文件的对象句柄。
  31. UnmapViewOfFile(pBuffer);
  32. CloseHandle(hMap);
  33. }
  1. 采用内存映射,对大文件进行分割。
  1. // experience4-1.cpp : 定义控制台应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #include <Windows.h>
  5. #include <iostream>
  6. #include <sstream>
  7. #include <fstream>
  8. #define iNumberOfFile 1000
  9. using namespace std;
  10. stringstream sstr1[iNumberOfFile];
  11. string szFileName[iNumberOfFile];
  12. string str[iNumberOfFile];
  13. int main()
  14. {
  15. SYSTEM_INFO sinf; //读大文件
  16. GetSystemInfo(&sinf);
  17. HANDLE hFile = CreateFile(TEXT("d://1//experience4-1.txt"), GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);//打开文件
  18. DWORD dwFileSizeHigh;
  19. _int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh); //获得文件大小
  20. qwFileSize += (((_int64)dwFileSizeHigh) << 32); //将高32位加到文件低32位上
  21. HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); //创建一个文件内核对象,大小默认为文件大小
  22. CloseHandle(hFile);
  23. _int64 qwFileOffset = 0; //每次映射文件大小,初始值为0
  24. int iFileName = 1;
  25. string szFilePath = "experience4-1_";
  26. while (qwFileSize > 0)
  27. {
  28. DWORD dwBytesInBlock = sinf.dwAllocationGranularity; //预定空间的分配
  29. if (qwFileSize < sinf.dwAllocationGranularity)
  30. dwBytesInBlock = (DWORD)qwFileSize;
  31. PCHAR pbFile = (PCHAR)MapViewOfFile(hFileMap,
  32. FILE_MAP_WRITE,
  33. (DWORD)(qwFileOffset >> 32), //高32位
  34. (DWORD)(qwFileOffset & 0xFFFFFFFF), //低32位
  35. dwBytesInBlock); //为文件的数据预定一块地址空间区域并将文件的数据作为物理存储器调拨给区域
  36. sstr1[iFileName] << iFileName;
  37. sstr1[iFileName] >> str[iFileName];
  38. szFileName[iFileName] = szFilePath + str[iFileName] + ".txt";
  39. ofstream fout(szFileName[iFileName]);
  40. if (fout)
  41. {
  42. cout << "Create: " << szFileName[iFileName] << " Success!" << endl;
  43. fout << pbFile << endl;
  44. }
  45. else
  46. cout << "Create: " << szFileName[iFileName] << " Error !" << endl;
  47. fout.close();
  48. iFileName++;
  49. UnmapViewOfFile(pbFile); //从进程空间撤销对文件数据的关联
  50. qwFileOffset += dwBytesInBlock;
  51. qwFileSize -= dwBytesInBlock;
  52. }
  53. system("pause");
  54. return 0;
  55. }

3. 实验结果(实验运行截图)

  1. 采用内存映射,实现进程数据共享。

【实验四】文件编程 - 图1

  1. 采用内存映射,对大文件进行分割。

【实验四】文件编程 - 图2

【实验四】文件编程 - 图3

5. 实验中的问题及心得

  • 第一个实验我使用vs运行时无论怎么操作在写入共享内存的数据后显示的仍然是要求写入数据,可能是我vs配置的问题,最后使用vc则可以正常运行。
  • Getchar()要在解除文件映射和关闭内存映射文件对象句柄之前,否则的话结果是错误的。
  • 由于实验2中要拆分一个2G的大文件,而我这里没有那么大的文件,并且那样分割的子文件太多,我就只是在目标文件里写了我自己的学号。
  • 如果大文件的内容较大时,运行有时能成功,有时则会导致程序崩溃至于解决办法还没有找到,估计还是我vs配置的问题,下来还要再修复下。
  • 掌握了文件管理以及文件内存映射的内容以及相关的api函数。

【实验四】文件编程 - 图4

6. 附件

以下是实验代码

链接:https://pan.baidu.com/s/1FSq_bQrGKZFWGAhit3a1_g
提取码:tx4x