给单文档的应用程序的菜单增加一个菜单“文件操作”,两个菜单项:“写入文件”、“读出文件”。为其添加消息响应函数。
先看看Win32API函数是如何使用的:
HANDLE CreateFile( LPCTSTR lpFileName, // file name
DWORD dwDesiredAccess, // access mode
DWORD dwShareMode, // share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
DWORD dwCreationDisposition, // how to create
DWORD dwFlagsAndAttributes, // file attributes
HANDLE hTemplateFile // handle to template file);
lpFileName :创建或者打开的对象的名称
dwDesiredAccess :对象的访问方式:有3中基本的方式:
0:查询访问
GENERIC_READ:读访问
GENERIC_WRITE:写访问
dwShareMode :共享模式
如果这个参数为0,表明不能被共享,而且在句柄被被关闭之前,不能被再次打开。如果想要共享,使用下面的标记:
FILE_SHARE_DELETE:如果是请求删除访问,那么对象后续打开操作将会成功
FILE_SHARE_READ:如果是请求读访问,那么对象后续打开操作将会成功
FILE_SHARE_WRITE:如果是请求写访问,那么对象后续打开操作将会成功
lpSecurityAttributes :指向一个SECURITY_ATTRIBUTES结构。这个结构决定了返回的句柄能否被继承。如果为NULL,不能被继承。在Windows NT/2000/XP下SECURITY_ATTRIBUTES指明了对象的安全描述子,如果为NULL,则使用默认的安全描述子且不能被继承。
dwCreationDisposition :指明了如果文件存在,那么会做什么事;文件不存在,会做什么事,有5中选择:
CREATE_NEW:创建新文件,如果文件已存在,则调用失败
CREATE_ALWAYS:创建新文件,如果文件已存在,则函数重写文件并清空现有属性
OPEN_EXISTING:打开文件,如果文件不存在,则调用失败
OPEN_ALWAYS:如果文件存在,则打开文件;如果文件不存在,则创建文件
TRUNCATE_EXISTING:打开文件,一旦文件打开,文件被截取以便它的大小为0字节,调用函数必须使用GENERIC_WRITE来访问打开文件,如果文件不存在,则函数调用失败
dwFlagsAndAttributes :指明了文件的属性和标记(选项太多,这里不列举了)
hTemplateFile :指定具有GENERIC_READ访问方式的模版文件的句柄。如果为此参数传递了一个文件句柄,则CreateFile会忽略为所创建的文件设置的属性标志,而是用hTemplateFile 所关联的文件的属性标志。
写文件使用函数WriteFile:
BOOL WriteFile( HANDLE hFile, // handle to file
LPCVOID lpBuffer, // data buffer
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten, // number of bytes written
LPOVERLAPPED lpOverlapped // overlapped buffer);
hFile :要写入的文件的句柄
lpBuffer :要写入文件的数据缓冲区的指针
nNumberOfBytesToWrite :指明要想文件中写入的字节数
lpNumberOfBytesWritten :用来接收实际写入文件的字节数
lpOverlapped :指向OVERLAPPED 结构的指针。如果这个参数想要起作用,那么CreateFile函数设置文件属性时需要加上FILE_FLAG_OVERLAPPED标记。
说了这么多,其实用起来也没有这么复杂:
void CCH_12_FILEView::OnWrite()
{
// TODO: Add your command handler code here
//文件句柄
HANDLE hFile;
hFile = CreateFile("5.txt", //名为"5.txt"
GENERIC_WRITE, //用来写
0, //不能被共享
NULL, //默认安全描述子,不能被继承
CREATE_NEW, //创建新文件,如果文件已存在,则调用失败
FILE_ATTRIBUTE_NORMAL, //没有其他属性
NULL); //必须为NULL
DWORD dwWrites;
WriteFile(hFile,"hello,world!",strlen("hello,world!"),
&dwWrites,NULL);
CloseHandle(hFile);
}
下面我们看文件的读取ReadFile:
BOOL ReadFile( HANDLE hFile, // handle to file
LPVOID lpBuffer, // data buffer
DWORD nNumberOfBytesToRead, // number of bytes to read
LPDWORD lpNumberOfBytesRead, // number of bytes read
LPOVERLAPPED lpOverlapped // overlapped buffer);
它的参数与WriteFile类似,这里就不多说了,直接看例子吧:
void CCH_12_FILEView::OnRead()
{
// TODO: Add your command handler code here
HANDLE hFile;
hFile = CreateFile("5.txt",
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
char ch[100];
DWORD dwReads;
ReadFile(hFile,ch,100,&dwReads,NULL);
ch[dwReads] = 0;
CloseHandle(hFile);
MessageBox(ch);
}
下面看看MFC对应的文件操作,MFC把与文件相关的操作都封装在了一个类:CFile中。
void CCH_12_FILEView::OnRead()
{
// TODO: Add your command handler code here
CFile file("6.txt",CFile::modeRead);
char *pBuf;
DWORD dwFileLen;
dwFileLen = file.GetLength();
pBuf = new char[dwFileLen + 1];
pBuf[dwFileLen] = 0;
file.Read(pBuf,dwFileLen);
file.Close();
MessageBox(pBuf);
}
void CCH_12_FILEView::OnWrite()
{
// TODO: Add your command handler code here
CFile file("6.txt",CFile::modeCreate| CFile::modeWrite);
file.Write("hello,world!",strlen("hello,world!"));
file.Close();
}
这是最基本的操作,我们下面看看稍微复杂一点的操作:“打开文件”对话框和“另存为”对话框。它们是通过CFileDialog类来实现的。
先看这个类的构造函数:
CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL );
bOpenFileDialog:如果为TRUE表明构造打开文件对话框,如果为FALSE表明构造另存为文件对话框
lpszDefExt:指定的默认文件扩展名,如果为NULL,则没有扩展名
lpszFileName:直线在对话框中的初始文件名,如果为NULL,则没有初始显示。
dwFlags:一个和多个标记的组合,允许定制文件对话框,参数的取值为OPENFILENAME中的Flags 值
lpszFilter:一连串的字符串对,用以指定一个或一组文件过滤器。
pParentWnd:指向对话框窗口的父窗口。
如果想改变对话框的一些属性,也可以修改成员变量m_ofn。这里着重介绍一下过滤的功能:这个功能在很多编辑类软件中都很常见:当打开一个文件打开对话框后,你可以通过选择“文件类型”来缩小你查找的要打开的文件的范围,它是通过m_ofn的lpstrFilter来实现的,举一个例子吧:
void CCH_12_FILEView::OnRead()
{
// TODO: Add your command handler code here
CFileDialog fileDlg(TRUE);
fileDlg.m_ofn.lpstrTitle = "我的文件打开对话框";
fileDlg.m_ofn.lpstrFilter = "TextFiles(*.txt)\0*.txt\0All Files(*.*)\0*.*\0\0";
if(IDOK == fileDlg.DoModal())
{
CFile file(fileDlg.GetFileName(),CFile::modeRead);
char* pBuf;
DWORD dwFileLen = file.GetLength();
pBuf = new char[dwFileLen + 1];
pBuf[dwFileLen] = 0;
file.Read(pBuf,dwFileLen);
file.Close();
MessageBox(pBuf);
}
}
void CCH_12_FILEView::OnWrite()
{
// TODO: Add your command handler code here
CFileDialog fileDlg(FALSE);
fileDlg.m_ofn.lpstrTitle = "我的文件保存对话框";
fileDlg.m_ofn.lpstrDefExt = "txt";
fileDlg.m_ofn.lpstrFilter = "TextFiles(*.txt)\0*.txt\0All Files(*.*)\0*.*\0\0";
if(IDOK == fileDlg.DoModal())
{
CFile file(fileDlg.GetFileName(),CFile::modeCreate | CFile::modeReadWrite);
file.Write("hello,world!!!!",strlen("hello,world!!!!"));
file.Close();
}
}
基本思路是:建立一个打开或者另存为的对话框,当用户点击确定按钮后,新建一个CFile类型的对象,然后利用这个类的函数完成文件的读写操作。
本章内容其实还有win.ini和注册表内容的读写。但是我觉得似乎暂时用不到它们,所以就不列出了。