VC++深入详解(10):文件的读写

来源:互联网 发布:通过域名查询ip 编辑:程序博客网 时间:2024/05/16 07:17
给单文档的应用程序的菜单增加一个菜单“文件操作”,两个菜单项:“写入文件”、“读出文件”。为其添加消息响应函数。
先看看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);//必须为NULLDWORD 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 hereHANDLE 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 hereCFile 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 hereCFile 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 hereCFileDialog 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 hereCFileDialog 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和注册表内容的读写。但是我觉得似乎暂时用不到它们,所以就不列出了。

原创粉丝点击