1. MFC的文件操作:
a. MFC专门提供CFile类进行文件操作;
b. 注意,CFile是MFC中特有的类,和C语言的文件操作和C++的文件操作没有关系,完全是MFC中特有的类;
c. CFile是MFC中所有文件类的基类,提供非缓冲方式的二进制输入输出功能,因此其效率非常高;
d. 打开文件的方法:
i. 在打开文件时一定先要创建一个CFile类对象,并将该对象和相关的文件相关联;
ii. 两种方法:
*1. 使用带参构造函数:CFile file(文件路径,打开文件的方式)
*2. 创建和关联分离,而使用无参构造函数和Open成员函数:
CFile file; file.Open(和带参构造函数中的参数一样)
iii. 其中路径就是目标文件的绝对路径或相对路径或者网络路径,其类型是一个字符串;
iv. 其中打开文件的方式有多种选择可以组合(这里只介绍几种最常用的模式):
*1. 首先它们都以CFile::作为前缀,表示这些都是CFile类中定义的静态变量,只属于类;
*2. modeCreate:创建模式,如果文件不存在就创建它,如果文件已存在则保留原文件的大小,但是清空里面的内容(即将文件长度截为0,但是文件所占的控件大小不变,即不释放);
*3. modeNoTruncate:不截断模式,即不将文件长度截断为0,一般和Create模式配合使用,当文件已存在,则直接打开而不将文件长度截为0,即保持原文件不变;
*4. shareDenyNone:即拒绝无的意思,也就是不拒绝任何东西,即来者不拒,这里的含义就是不禁止其它文件同时读写该文件,但如果文件已经被其它进程以兼容模式访问时将打开文件失败(即如果其它进程在访问该文件时加了读锁或者写锁则该文件就不能被打开,兼容模式就是指加锁);
*5. shareDenyRead:可以共享其它进程访问该文件,但是拒绝其它文件读取该文件,即加读锁,同样也只要其它进程已经以兼容模式打开该文件时打开文件将失败;
*6. shareDenyWrite:和前面的一样,只不过加的是写锁,即比人不能写但能读;
*7. modeRead:只读方式;
*8. modeWrite:写方式;
2. 使用MFC的文件操作读写文件:
a. 建立一个支持MFC的控制台应用程序;
b. 注意:其中_tmain函数就是main的宏,即#define _tmain main;
c. 在main函数中添加写文件的代码:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CFile file("M:\\Test Programs\\VC6.0\\Test.txt",
CFile::modeCreate |
CFile::modeNoTruncate |
CFile::modeWrite |
CFile::shareDenyNone
);//这里是以写的方式将文件打开
//并且如果该文件不存在就创建该文件
//如果该文件存在则不将其长度截为0
//并且不加任何锁,但是其它进程以兼容模式访问该文件将打开失败
CString str;
for (int i = 1 ; i <= 20 ; i++)
{
//只要涉及到Windows应用程序编程(涉及到Win32 API编程和MFC编程)
//精确地讲,就是使用Windows系统提供的函数来处理字符串时一个换行符等于\r\n两个字符!!!
//但是在C语言和C++编程的时候就不存在这个问题,因为Visual编译器都实现了ANSI标准而不是微软自己的标准
str.Format("这是第%d行\r\n", i);
//第一个参数是带写入字符串的指针,这里直接使用CString对象就行了,指针已经封装在对象里面了
//第二个参数是要写入的内容的字节数,这里直接调用CString类的成员函数GetLength就可以获得
//注:这里的写入是从当前文件指针位置处写入而不是从文件头部写入就,文件指针会随着内容的写入不断偏移
file.Write(str, str.GetLength());
}
file.Close();//写完以后就要关闭文件,这里的关闭是指释放文件在内存中的映射
}
return nRetCode;
}
d. 在MFC的图形界面下将刚刚写入的内容读取:
i. 代码示例(main函数体):
CFileDialog dlg(TRUE);//创建一个“打开文件”对话框
if (IDCANCEL == dlg.DoModal())//用DoModal创建并显示该“打开文件”对话框,并判断用户是否退出该对话框
return 0;
//注意,用户是在图形界面下鼠标选择路径,因此这个路径时实时更新到对话框的路径变量中的,因此不需要使用UpdateData
CString path = dlg.GetPathName();//利用该成员函数可以返回用户选择的路径名
CFile _file(path, CFile::modeRead | CFile::shareDenyNone);//以只读并且不加锁的模式打开文件
//Read的第一个参数是void *类型的,而Write的第一个参数是const void *类型的
//但是CString类型定义了从CString类型到const void *的转换但是没有定义到void *类型的转换
//因此不能讲CString类型对象作为Read函数的第一个参数
//也就是说不能直接将文件中的内容通过Read函数读取到CString对象中去
//因此只能用char数组的方式暂存文件中的内容了
int iBufLen = _file.GetLength() + 1;//先定义char数组(即内存中缓冲区的长度)
//最后一位留给'\0'作为字符串结束符,因为这是在控制台上输出
char *pBuf = new char [iBufLen];//注意Windows源程序变量命名规则,执
//该函数第一个参数是内存块的首地址
//第二个参数是一个字符
//第三个参数是一个指定长度
//意思就是将指定内存块的指定长度中的数据全部置为第二个参数指定的数据
//它是一种将较大结构体或数组清零的最快操作!!
//这里就是将这个内存块清零
memset(pBuf, 0, iBufLen);
//第二个参数同样指定读取的字节数
//该函数返回实际读入的字节数
//可能存在异常情况(比如内存占满等)导致读取不了全部字节
//这里做了简化,如果发生这种情况那么在读取的最后一个字节的位置后面可能是一个随机数而不是
//字符串结束符,而导致后面printf函数输出异常,因此这里一定要先使用memset清零
//当然也可以使用if语句判断Read的返回值是否等于文件的字节长,如果不是则退出程序等
_file.Read(pBuf, _file.GetLength());
_file.Close();//用完以后立马关闭
printf("%s", pBuf);
delete [] pBuf;
pBuf = NULL;//逢野必空
ii. CFileDialog类简介:
*1. 它是一种对话框类,只不过是专门处理文件的对话框,即"打开文件"和”另存为“两种;
*2. 构造函数:
第一个参数:为BOOL值,如果为TRUE则创建的是一个”打开文件“对话框,否则就是一个”另存为“对话框,无默认值必须在编程时指定;
第二个参数:为字符串,默认值为NULL,即指定文件的默认扩展名,即如果用户没有输入文件的扩展名则将该值作为默认的扩展名,如果为NULL,则不添加;
第三个参数:为字符串,默认值为NULL,即指定文件的路径,如果默认值设为NULL,则不会自动为用户生成文件名而需要用户自行输入;
第四个参数:指定对话框风格,有默认风格,一般编程时不指定(因为默认风格是标准的);
第五个参数:提供可选择的文件类型和扩展名;
第六个参数:指定父窗口类的指针(因为这是一个控制台程序,因此该对话框就是主对话框无父窗口,如果是在MFC中,则一般来说父窗口都是View类);
iii. 向文件末尾追加内容:先使用CFile类的成员函数SeekToEnd(),将文件指针设置到文件末尾,然后再使用Write函数就行了;