才写完了作业,碰到了一些问题,也学会了很多,写出来总结下,也让碰到此问题的人有个答案。在写之前刚刚看打了《2010中国大学创业富豪榜》,有的才26,突然觉得很失落。好了,不管那了,进正题。
此次的作业主要是利用内存映射文件技术,实现如显示,写入,进程间共享等。先解释内存映射文件,如果说的不那么专业的话,就是将磁盘上的文件映射到物理内存中(可以是文件的一部分,可控制映射的大小),一方面可以解决大文件的处理,另一方面可以进程间共享数据(类似于命名管道,但映射的文件是磁盘中现实的文件)。优势以及专业解释再搜一搜了。
这里主要介绍遇到的两个问题。一是想在内存映射文件实际的大小后追加内容,而不是固定的写入很多无用字节。另一个问题不算问题,但是要提一下,就是进程间(或者两个程序)使用SendMessage()时,收不到消息的问题。
问题一:要使用内存映射文件,主要有下面几个步骤,请看参考学习的网页上【1】:
// 步骤1 打开文件FILE_FLAG_WRITE_THROUGH
HANDLE hFile = CreateFile()
if (hFile != INVALID_HANDLE_VALUE)// 文件打开失败返回句柄为-1
// 步骤2 建立内存映射文件
DWORD dwFileSize = GetFileSize(hFile, NULL);//获取文件大小
HANDLE hFileMap = CreateFileMapping()
if (hFileMap != NULL)//成功获取则非空
// 步骤3:将文件数据映射到进程的地址空间
PVOID pvFile = MapViewOfFile( )//pvFile就是得到的指针,用它来直接操作文件,
if (pvFile != NULL)
// 步骤4: 像操作内存一样操作文件,演示功能把整个文件倒序
char *p = (char*)pvFile;
printf("%s/n", p);
// 步骤5: 相关的释放工作
UnmapViewOfFile(pvFile); // 释放内存映射文件的头指针
CloseHandle(hFileMap); // 内存映射文件句柄
CloseHandle(hFile); // 关闭文件
一般的使用也就这么几个步骤,除了显示,还可以进行写入,主要利用pvFile这个指针,可以(char*)pvFile[i]= 这样写入,但要注意的是i不能超过原来文件的字节数或者说上面获得的dwFileSize(文件大小),否则写回的时候是不会写到文件里的。如果上面的参数中,你设置了文件映射到内存中的大小,那么即使你没有写够,在文件从内存中释放后也会写入你设置的大小数量的内容,你没写的就默认补/0了。
那么我想在文件打开后,在原来文件末尾追加我要的字符,而后又将实际的文件大小写回呢(即使设置了映射的文件大小)?其实对于编程经常操作文件的人来说很简单,可是我不常用,只好学习了【2】,主要利用了几个函数如下:
在内存映射文件操作完成后,先释放资源
::UnmapViewOfFile(pvFile);
::CloseHandle(hFileMap);
再设置文件大小为正确的大小
::SetFilePointer(hFile, dwFileSize, NULL, FILE_BEGIN); //主要函数:将文件的指针指到你所写的内容结尾
::SetEndOfFile(hFile);//主要函数:设置文件结束。具体的可查MSDN,如果使用FlushMapViewOfFile(将内存中的内容写回磁盘)也可以达到效果
::CloseHandle(hFile);
问题二:vc 进程间通信,有很多方法,参考【3】中提到了11种,我没试验过。我这里用了一种最简便的方法也就是直接使用SendMessage();和在窗体(我是在对话框)中重载了WM_COPYDATA消息,来接收SendMessage()发送来的消息。需要注意的是:
SendMessage(),有两种,MSDN上如下:
LRESULT SendMessage(
UINT message,
WPARAM wParam = 0,
LPARAM lParam = 0
) throw();
static LRESULT SendMessage(
HWND hWnd, //你说要发送的窗体的句柄,可以通过::FindWindow(NULL,窗体名(不确定可以从任务管理器看));
UINT message, //要发送的消息,我这里使用的是WM_COPYDATA
WPARAM wParam, //附加消息,可以为NULL
LPARAM lParam //千万注意了不要想的自己没必要传递数据而设为NULL,必须把其中的COPYDATASTRUCT填满,不然就会莫名其妙的收不到消息了,就是这个害得我好惨!注意,千万注意!
) throw();
显然,如果我们是进程间通信,要用第二种,在程序中就是::SendMessage();就可以了。
好了,就写这么多了,有问题了请提醒我,不够专业,见谅。
参考网页:
【1】http://hi.baidu.com/codeworkman/blog/item/f983c7f580908fd0f2d385bd.html
【2】http://topic.csdn.net/u/20090629/11/94a40de4-92f3-4609-b3e3-fffb60d0dcf2.html
【3】http://www.360doc.com/content/10/1027/11/1944251_64404287.shtml