用VC++编写对文件File的打开、写入、读取、关闭等操作时,分别可以用C语言,C++类,Win32 API以及MFC类来实现。下面对通过这几种方式实现文件的操作进行一个简单的概述,拾人牙慧,有错误的地方,请大佬们不吝赐教。
一、C语言
C语言对文件的打开与创建需要用到FILE结构体,其中用到的函数为:
errno_t _wfopen_s(FILE*file, const wchar_t* filename, const wchar_t* mode);
该函数有三个参数,第一个参数是将要返回的FILE结构体指针,第二个参数(filename)是一个指向文件名字符串常量的指针,即该指针可以指向不同的字符串文件名,但不能通过该指针来修改文件名,例如:_T("test.txt"),第三个参数(mode)是指文件的打开模式,可以取如下值:
_T("r"):为读取而打开;
_T("w"):为写入操作打开一个空文件。如果给定的文件已经存在,则文件的内容将被清空;
_T("a"):为写入操作打开文件。如果文件已经存在,那么在该文件尾部添加新数据,在写入新数据之前,不会移除文件中已有的EOF标记;如果文件不存在,则首先创建这个文件;
_T("r+"):打开文件用于写入操作和读取操作,文件必须存在;
_T("w+"):为写入操作和读取操作打开一个空的文件。如果给定文件已经存在,那它的内容将被清空;
_T("a+"):打开文件用于读取操作和添加操作。并且添加操作在添加新数据之前会移除该文件中已有的EOF标记,然后当写入操作完成之后再恢复EOF标记。如果指定的文件不存在,则首先将创建这个文件。
当然还可以与b组合,组成_T("rb")或_T("wb")等,在这里b的意思为二进制,即以二进制的形式打开文件。
函数返回0表示成功,失败的话将返回一个错误代码。
C语言向文件中写入数据用fwrite函数实现:
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
fwrite函数的四个参数,第一个buffer是一个指针变量,指向将要被写入文件中的数据。第二个参数size为以字节为单位的一项数据的大小,比如int型数据为4个字节,则size为4。第三个参数count为将要被写入的项的最大数目,比如要写入10个int型数据,则size为4,count为10,则最终要写入的数据量为size*count个字节。第四个参数stream是指向用fopen函数打开文件时返回的FILE结构体指针。
例:
FILE* pFile;
_wfopen_s(pFile,_T("test.txt"),_T("w")); //以写的方式在工程目录下打开文件名为test.txt的文件
fwrite(_T("This is my first file test program"),2,wcslen(_T("This is my first file test program")),pFile);
由于宽字符下一个字符占2个字节,因为size参数取2,而wcslen函数将返回字符串中字符个数。
C语言从文件中读取数据用fread函数实现:
size_t fread(void* buffer, size_t size, size_t count, FILE* stream);
该函数有四个参数,后面三个参数与fwrite函数中的参数一样,第一个参数buffer是一个指针,指向用来存放数据的缓冲区。
文件打开,在完成了读写操作之后,需要关闭,可以用fclose(FILE* pFile)函数关闭;此外,程序中数据用fwrite函数写入之后,是存在于内存中的一块特定缓冲区中,需要等该缓冲区填满之后或者程序关闭之后才会送到磁盘文件中,这时可以用fflush(FILE* pFile)函数来刷新数据写入。另外文件中存在一个文件指针,用来定位当前读写的位置,可以用int fseek(FILE* stream, long offset, int origin)函数来实现文件指针的移动操作。
二、C++
C++对文件的读写操作需要用到ofstream类和ifstream类,其构造函数如下
wofstream(const wchar_t* szName,int nMode=ios::out, int nProt=filebuf::openprot);
ofstream类的构造函数有三个参数,第一个参数szName为将要打开的文件名,第二个参数nMode为文件打开的模式,可以取如下值 :
ios::app 函数将执行一个定位操作,将文件指针移动到文件的结尾。当向文件写入新数据时,将总是添加到文件的末尾处,即使已经用ostream::seekp函数移动了文件指针的位置;
ios::ate 函数将执行一个定位操作,将文件指针移动到文件的结尾。当向文件写入第一个新的字节数据时,将在文件的末尾处添加。但随后写入的其他字节的数据,将被写入到当前位置;
ios::in 如果指定了此模式,则原始文件(如果存在的话)将不会被截断;
ios::out 打开文件,用于输出;
ios::trunc 如果文件已经存在,则它的内容将被清空;
ios::nocreate 如果文件不存在,则函数失败;
ios::noreplace 如果文件已经存在,则函数失败;
ios::binary 以二进制方式打开文件;
第三个参数nProt为文件保护规格说明,可取如下值:
filebuf::sh_compat 兼容共享模式
filebuf::sh_none 排他独占模式,不共享
filebuf::sh_read 允许读共享
filebuf::sh_write 允许写共享
向文件中写数据则利用ofstream::write()函数;
wifstream类与wofstream类构造函数相同,可以用ifstream::read()函数从文件中读取数据;
文件数据写入或读取结束之后,可以调用ofstream::close()或ifstream::clse()函数关闭文件;
Note:在这里有一点需要注意,如果想要通过wofstream对象输出中文到文件中,或者通过wifstream对象从文件中读取中文,则需要先把全局语言环境设置为本地语言环境,即:
locale& loc=locale::global(locale(locale(),"",LC_CTYPE));//将全局语言环境设置为本地语言
...
locale::global(loc);//恢复之前的全局语言环境
三、Win32 API
Win32中可以利用CreateFile,ReadFile,WriteFile函数来完成文件的创建、打开、写入和读取。
HANDLE CreateFile(
LPCTSTR lpFileName, //创建或打开的对象的名称
DWORD dwDesireAccess, //对对象的访问方式
DWORD dwShareMode, //共享方式
LPSECURITY_ATTRIBUTES lpSecurityAttributes,//指向一个SECURITY_ATTRIBUTES结构体
DWORD dwCreationDisposition, //指定如何创建文件
DWORD dwFlagsAndAttributes, //设置文件属性和标志
HANDLE hTemplateFile //指向具有GENERIC_READ访问方式的模板文件的句柄
);
BOOL WriteFile(
HANDLE hFile, //将要写入数据的文件的句柄
LPCVOID lpBuffer, //指向将要写文件的数据缓冲区
DWORD nNumberOfBytesToWrite, //将向向文件中写入的字节数
LPDWORD lpNumberOfBytesWritten, //用来接收实际写入到文件中的字节数
LPOVERLAPPED lpOverlpaaed //指向OVERLAPPED结构体
);
BOOL ReadFile(
HANDLE hFile, //将要读取数据的文件的句柄
LPVOID lpBuffer, //用来接收从文件中读取的数据的缓冲区指针
DWORD nNumberOfBytesToRead, //将要从文件中读取的字节数
LPDWORD lpNumberOfBytesRead, //用来接收实际读到的字节数
LPOVERLAPPED lpOverLapped //指向OVERLAPPED结构体
);
四、MFC类
MFC中通过基类CFile类及其派生类提供对文件的操作。
CFile的构造函数如下:
CFile(LPCTSTR lpszfileName, UNIT nOpenFlags);
该构造函数有两个参数,第一个参数lpszFileName指定文件的名称,第二个参数nOpenFlags指定文件共享和访问的方式。
nOpenFlags可以取如下值:
CFile::modeCreate 创建一个新文件。如果该文件已经存在,那么将它的长度截断为0;
CFile::modeNoTruncate 与CFile::modeCreate 组合使用。如果正创建的文件已经存在,那它的长度不会被截断为0;
CFile::modeRead 打开文件,该文件仅用于读取操作;
CFile::modeReadWrite 打开文件,该文件可读可写;
CFile::modeWrite 打开文件,该文件仅用于写入操作;
CFile::modeNoInherit 禁止子进程继承该文件;
CFile::modeShareDenyNone 打开文件,同时并不拒绝其他进程对该文件的读取或写入访问;
CFile::modeShareDenyRead 打开文件,并且拒绝其他进程对该文件的读取访问;
CFile::modeShareDenyWrite 打开文件,并且拒绝其他进程对该文件的写入访问;
CFile::modeShareExclusive 以排它独占模式打开文件,拒绝其他进程对该文件的读取和写入访问;
CFile::modeShareCompact 此标志在32位MFC中不可用;
CFile::typeText 设置文本模式,带有一对回车换行字符(仅在CFile类的派生类中使用)
CFile::typeBinary 设置二进制模式(仅在CFile类的派生类中使用)
CFile类中提供了很多方法供文件的操作使用,写入数据可以调用Write方法,读取数据可以调用Read方法,Seek方法可以将文件指针移动到指定的位置,GetLength方法获得文件的长度。