第13章文件操作.docx
《第13章文件操作.docx》由会员分享,可在线阅读,更多相关《第13章文件操作.docx(49页珍藏版)》请在冰豆网上搜索。
![第13章文件操作.docx](https://file1.bdocx.com/fileroot1/2023-2/25/b29117ab-b342-4451-9e8e-3b254a2c5867/b29117ab-b342-4451-9e8e-3b254a2c58671.gif)
第13章文件操作
第13章文件操作
本章包括:
使用WindwosAPI进行文件读写;
使用C运行时库进行文件读写;
使用CFile类进行文件读写;
使用CStdioFile类进行文件读写;
INI文件的读写;
注册表的读写。
文件是在计算机内存中以二进制表示的数据在外部存储介质(硬盘、U盘等)上的另一种存储方式,这种存储方式是一种永久性的方式,它不随电信号的消逝而消失。
文件通常分为二进制文件和文本文件,二进制文件一般用来作为可执行程序、图形、图像、音视频文件的存储介质;文本文件也称为ASCII文件,它的每一个字节存放的是可表示为一个字符的ASCII代码的文件。
它是以“行”为基本结构的一种信息组织和存储方式的文件,可用任何文字处理程序阅读的简单文本文件。
13.1读写文件
文件的读写方式有很多中,可以使用WindowsAPI进行文件读写,也可以使用C运行时库函数进行文件读写,如果上述方式对使用者来说太繁杂,微软甚至为使用者提供了具有良好接口的MFC类,它将文件的读写操作进行了封装,使文件的读写操作变得更加容易。
下面就将对文件读写操作的几种常用方式进行一一介绍。
13.1.1使用WindowsAPI
Windows操作系统为Windows应用开发人员提供了一系列对文件进行操作的接口函数。
Windows提供的文件操作函数主要有下面4个:
❑CreateFile函数:
实现文件的创建或打开操作。
❑WriteFile:
实现文件的数据写入操作。
❑ReadFile:
实现文件数据的读取操作。
❑CloseHandle:
实现文件的关闭操作。
下面将详细的介绍这些函数并给出实际应用中常见的示例。
(1)CreateFile函数用来创建或打开文件,其语法格式如下所示:
HANDLECreateFile(
LPCTSTRlpFileName,
DWORDdwDesiredAccess,
DWORDdwShareMode,
LPSECURITY_ATTRIBUTESlpSecurityAttributes,
DWORDdwCreationDisposition,
DWORDdwFlagsAndAttributes,
HANDLEhTemplateFile);
该函数用来创建或者打开一个文件对象,并返回一个可以用来访问此文件对象的文件句柄,其参数详解如下:
❑lpFileName:
需要创建或者打开的文件对象的名字。
❑dwDesiredAccess:
标识文件的访问权限,例如:
GENERIC_READ文件能够被读取;GENERIC_WRITE能够向文件写入数据。
❑dwShareMode:
标识文件进行共享的方式,例如:
0表示不共享文件;FILE_SHARE_READ:
允许读共享;FILE_SHARE_WRITE:
允许写共享。
❑lpSecurityAttributes:
定义文件的安全特性,一般为NULL,使用默认安全属性。
❑dwCreationDisposition:
定义对指定文件的操作方式,可以为下述常数之一:
CREATE_NEW创建新文件,如文件存在则会出错。
CREATE_ALWAYS创建新文件,如果文件已经存在,会改写文件的属性
OPEN_EXISTING打开文件,文件必须已经存在,否则函数调用失败
OPEN_ALWAYS打开文件,如文件不存在则创建它。
TRUNCATE_EXISTING将现有文件缩短为零长度。
❑dwFlagsAndAttributes:
定义文件属性,例如:
FILE_ATTRIBUTE_HIDDEN文件具有隐藏属性FILE_ATTRIBUTE_NORMAL文件具有默认属性。
❑hTemplateFile:
如果不为零,则指定一个文件句柄。
新文件将从这个文件中复制扩展属性。
❑此函数如果调用成功将返回打开文件的文件句柄,如果调用失败将返回INVALID_HANDLE_VALUE,使用GetLastError()可以获得具体的错误码。
下面是使用该函数打开一个已经存在文件”c:
\\TestFileApi.txt”的范例:
HANDLEhFile;//声明一个句柄变量
hFile=CreateFile("c:
\\TestFileApi.txt",GENERIC_WRITE,0,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);//打开文件
if(hFile==NULL||hFile==INVALID_HANDLE_VALUE)
{
intnErrorCode=:
:
GetLastError();//获取错误代码
}
(2)ReadFile函数用来读取文件数据,其语法格式如下所示:
BOOLReadFile(
HANDLEhFile,
LPVOIDlpBuffer,
DWORDnNumberOfBytesToRead,
LPDWORDlpNumberOfBytesRead,
LPOVERLAPPEDlpOverlapped
);
该函数用来从文件中读取数据,其参数详解如下:
❑hFile:
需要读取数据的文件句柄。
❑lpBuffer:
用于保存读入数据的缓冲区。
❑nNumberOfBytesToRead:
本次操作要读取的字节数。
❑lpNumberOfBytesRead:
返回本次操作实际读取的字节数。
❑lpOverlapped:
该结构定义了一次异步读取操作。
否则,应将这个参数设为NULL。
下面是读取一个已经打开文件的范例:
DWORDdwBytesRead=0;//声明一个DWORD变量并赋初值0
charszBuf[1000];//声明字符数组作为数据缓存
BOOLbRet=:
:
ReadFile(hFile,szBuf,sizeof(szBuf),&dwBytesRead,NULL);
if(bRet==NULL)//读取文件失败
{
MessageBox("读取文件失败");
return;
}
szBuf[dwBytesRead]=0;//为读出的字符串加上结束符'\0'
MessageBox(szBuf);//使用弹出对话框显示读取的数据
(3)WriteFile用来向指定文件写入数据,其语法格式如下所示:
BOOLWriteFile(
HANDLEhFile,
LPCVOIDlpBuffer,
DWORDnNumberOfBytesToWrite,
LPDWORDlpNumberOfBytesWritten,
LPOVERLAPPEDlpOverlapped
);
该函数用来向指定的文件中写入数据,其参数详解如下:
❑hFile:
需要写入数据的文件句柄。
❑lpBuffer:
要写入文件的数据缓冲区。
❑nNumberOfBytesToWrite:
本次操作要写入数据的字节数。
❑lpNumberOfBytesWritten:
本次操作实际写入的字节数。
❑lpOverlapped:
该结构定义了一次异步读取操作。
否则,应将这个参数设为NULL。
下面是向一个已经打开的文件写入数据的范例:
DWORDdwBytesWritten=0;//声明一个DWORD变量并赋初值0
CStringstrTextData=“datadatadata”;//写入文件的数据缓存
BOOLbRet=:
:
WriteFile(hFile,m_strTextData,strTextData.GetLength(),
&dwBytesWritten,NULL);//向文件写数据
if(bRet==FALSE||dwBytesWritten!
=strTextData.GetLength())
{
MessageBox("向文件写入数据失败");//显示数据
}
(4)CoseHandle用来关闭文件,其语法格式如下所示:
BOOLCloseHandle(
HANDLEhObject
);
该函数用来关闭文件,释放文件句柄,其参数详解如下:
❑hObject:
需要关闭的文件的文件句柄对象。
下面是关闭一个已经打开的文件的范例:
if(hFile!
=NULL||hFile!
=INVALID_HANDLE_VALUE)//判断文件句柄是否有效
{
CloseHandle(hFile);//关闭文件
hFile=NULL;
}
注意:
在使用CreateFile打开文件后,如果不调用CloseHandle进行文件句柄的释放操作,将导致句柄资源泄露。
13.1.2使用C运行时库
C语言提供了一套C运行时库函数来进行文件的操作。
缓冲文件系统中,有一个“文件指针”概念。
每一个被使用的文件都在内存中开辟一个区来存放文件的相关信息,比如:
文件的名字、文件状态以及文件当前位置等。
这些信息被保存在一个结构体变量中,该结构体类型由系统定义,名字为FILE。
在stdio.h中,其定义如下:
typedefstruct{
shortlevel;//缓冲区“满”或“空”的程度
unsignedflags;//文件状态标志
charfd;//文件描述符
unsignedcharhold;//如无缓冲区不读取字符
shortbsize;//缓冲区大小
unsignedchar*buffer;//数据缓冲区的位置
unsignedchar*curp;//指针当前的指向
unsignedistemple;//临时文件,指示器
shorttoken;//用于有效性检查
}FILE;
C运行时库提供的文件操作函数主要有下面4个:
❑fopen函数:
实现了文件的创建或打开操作。
❑fread函数:
实现了文件数据的读取操作。
❑fwrite:
实现了写入文件数据的操作。
❑fclose:
实现了关闭文件的操作。
下面将详细的介绍这些函数并给出实际应用中常见的示例。
(1)fopen函数用来创建或打开文件,其语法格式如下所示:
FILE*fopen(constchar*filename,constchar*mode);
该函数用来创建或打开一个文件,其参数详解如下:
❑filename:
欲创建或打开的文件路径及文件名。
❑mode:
文件打开的方式,代表流的形态,例如:
”r”为输入打开一个文本文件;”w”为输出打开一个文本文件;”rb”为输入打开一个二进制文件;”wb”为输出打开一个二进制文件。
❑如果函数调用成功,将返回包含该文件相关信息的文件文件结构FILE的指针,否则将返回NULL。
下面是打开一个记事本文件的范例:
FILE*fp=fopen("test.txt","w+");//为读写建立一个新的文本文件
if(fp==NULL)//打开文件失败
{
MessageBox("打开文件失败");
}
(2)fread函数用来从文件读取数据,其语法格式如下:
size_tfread(void*buffer,size_tsize,size_tcount,FILE*stream);
该函数用来从指定的文件中读取数据,其参数详解如下:
❑buffer:
用来接收数据的缓冲区。
❑size:
欲读取的元素大小。
❑count:
欲读取的元素个数。
❑stream:
提供数据的文件指针。
❑函数调用成功将返回实际读取字节数。
下面是从一个已经打开的文件读取数据的范例:
charszBuf[1000];//声明字符数组作为数据缓存
size_tnBytesRead=0;
nBytesRead=fread(szBuf,10,1,fp);//从文件读取10个字节
szBuf[10]=0;//为读出的字符串加上结束符'\0'
MessageBox(szBuf);//使用弹出对话框显示读取的数据
(3)fwrite函数用来向指定文件写入数据,其语法格式如下:
size_tfwrite(constvoid*buffer,size_tsize,size_tcount,FILE*stream);
该函数用来向指定的文件中写入数据,其参数详解如下:
❑buffer:
要写入文件的数据缓冲区。
❑size:
要写入的字节数。
❑count:
要写入多少个size字节的数据项。
❑stream:
欲写入数据的文件指针。
❑函数调用成功将返回实际写入的字节数。
下面是向一个已经打开的文件中写入数据的范例:
charszTextData[]=“datedatedate”;//数据缓存
fwrite(szTextData,sizeof(szTextData),1,fp);//写文件
(4)fclose函数用来关闭文件,其语法格式如下:
fclose(FILE*stream);
该函数用来关闭文件,其参数详解如下:
❑stream:
欲关闭的文件结构对象。
下面是关闭一个处于打开状态的文件的范例:
if(fp!
=NULL)//判断文件指针有效性
fclose(fp);//关闭文件
13.1.3使用CFile类
CFile是MFC文件类的基类,该类将文件的操作进行了封装,通常,一个磁盘文件在CFile构造时自动打开并在析构时关闭。
静态成员函数使你可以在不打开文件的情况下检查文件状态。
通常在构造CFile对象时在其构造函数中指定要操作的物理文件对象以及具体的操作方式,CFile类提供的文件操作函数主要有下面4个:
❑CFile:
:
CFile:
构造函数,实现了文件的打开操作。
❑CFile:
:
Read:
实现了读取文件数据的操作。
❑CFile:
:
Write:
实现了向文件写入数据的操作。
❑CFile:
:
Close:
实现了文件关闭操作。
下面将详细的介绍这些函数并给出实际应用中常见的例子。
(1)CFile:
:
CFile为构造函数,用来加载文件,实现文件的打开操作,其语法格式如下:
CFile:
:
CFile(LPCTSTRlpszFileName,UINTnOpenFlags);
该函数为CFile类的构造函数,它将在对象被创建时由系统自动调用,进行文件对象的打开或创建操作,其参数详解如下:
❑lpszFileName:
欲创建或打开的物理文件路径。
❑nOpenFlags:
指定文件的访问权限欲共享标识,例如:
CFile:
:
modeRead以只读的方式打开文件;CFile:
:
modeReadWrite以可读写的方式打开文件。
下面是使用其构造函数打开一个文件的范例:
CFilefile("test.txt",CFile:
:
modeRead);//打开文件
(2)CFile:
:
Read函数用来读取文件数据,其语法格式如下:
UINTCFile:
:
Read(void*lpBuf,UINTnCount);
该方法用来从文件中读取数据,其参数详解如下:
❑lpBuf:
用来接收数据的缓冲区。
❑nCount:
本次操作要读取的数据量。
❑如果方法调用成功将返回本次操作实际读取的字节数,如果读到了文件末尾,返回的实际读取的字节数可能会小于nCount指定需要读取的字节数量。
下面是使用该方法读取文件数据的范例:
charszBuf[1000];//声明字符数组作为数据缓存
UINTuBytesRead=0;//声请一个无符号整型变量
uBytesRead=file.Read(szBuf,sizeof(szBuf));//读文件
szBuf[uBytesRead]=0;//为读出的字符串加上结束符'\0'
MessageBox(szBuf);//使用弹出对话框显示读取的数据
(3)CFile:
:
Write函数用来向文件写入数据,其语法格式如下:
voidCFile:
:
Write(constvoid*lpBuf,UINTnCount);
该方法向指定的文件对象中写入数据,其参数详解如下:
❑lpBuf:
欲写入文件的数据缓冲区。
❑nCount:
写入文件的数据字节数。
下面是使用该方法向文件写入数据的范例:
charszTextData[]=“datedatedate”;//数据缓存
file.Write(szTextData,sizeof(szTextData));//向文件写数据
(4)CFile:
:
Close函数用来关闭文件对象,其语法格式如下:
voidCFile:
:
Close();
该方法用来关闭一个文件,即将句柄对象与实际的物理文件解除关联,并释放句柄对象。
下面是关闭一个文件的范例:
file.Close();//关闭文件
当心:
如果使用CFile类对象打开一个文件后未调用Close方法进行关闭,会导致句柄资源泄露。
13.1.4使用CStdioFile类
CStdioFile类继承自CFile,一个CStdioFile对象代表一个用运行时C库函数fopen打开的C运行时流式文件。
当将一个换行符(0x0A)写入一个文本方式的CStdioFile对象时,字节对(0x0D,0x0A)被发送给该文件。
当读一个文件时,字节对(0x0D,0x0A)被翻译为一个字节(0x0A)。
与CFile一样,文件的打开操作是在构造函数中去完成的,在CStdioFile的构造式中需要指定欲创建或打开的文件,并指定对文件的操作方式,CStdioFile提供的文件操作函数主要有下面4个:
❑CStdioFile:
:
CStdioFile:
构造函数,实现了文件的打开操作。
❑CStdioFile:
:
ReadString:
实现了读取文件数据的操作。
❑CStdioFile:
:
WriteString:
实现了向文件写入数据的操作。
❑CStdioFile:
:
Close:
实现了文件关闭操作。
下面将详细的介绍这些函数并给出实际应用中常见的例子。
(1)CStdioFile:
:
CStdioFile为构造函数,用来加载文件,实现文件的打开操作,其语法格式如下:
CStdioFile:
:
CStdioFile(LPCTSTRlpszFileName,UINTnOpenFlags);
其参数详解如下:
❑lpszFileName:
欲操作的文件路径。
❑nOpenFlags:
文件的操作方式,其定义与父类CFile相同。
下面是使用其构造函数加载一个文件的范例:
CStdioFilestdFile("test.txt",CFile:
:
modeRead);//打开文件
(2)CStdioFile:
:
Read函数用来读取文件数据,其语法格式如下:
BOOLCStdioFile:
:
ReadString(CString&rString);
该函数读取一行文本到缓冲区rString,遇到回车换行符停止读取。
回车和换行符不读到rString,而且末尾也不添加“\0”。
下面是使用该方法读取文件数据的范例:
CStringstrBuf;
if(!
stdFile.ReadString(strBuf))//读一行
{
MessageBox("读文件失败");
return;
}
MessageBox(strBuf);//使用弹出对话框显示读取的数据
(3)CStdioFile:
:
WriteString函数用来向文件写入数据,其语法格式如下:
voidCStdioFile:
:
WriteString(LPCTSTRlpsz);
该函数将缓冲区lpsz中的数据写入与CStdioFile对象关联的文件中。
其参数详解如下:
❑lpsz:
欲写入文件的数据缓冲区
注意:
结束字符“\0”不被写入该文件。
lpsz中的所有换行符都被以一个硬回车换行符对写入该文件,即“\n”被转化成“\r\n”写入到文件里。
下面是使用该方法读取文件数据的范例:
CStringstrTextData=“datetatedate”;//数据缓存
stdFile.WriteString(strTextData);//写文件
(4)Close函数用来关闭文件,此函数继承自父类CFile,下面是使用该方法关闭文件的范例:
stdFile.Close();//关闭文件
13.1.5案例:
使用4种文件操作方式读写文件
该小节我们来结合一个实际例子,介绍文件读写的几种常用方法。
(1)创建一个基于对话框的工程。
启动VC++6.0单击Projects选项卡,在列表框中选择MFCAppWizard(exe),在Projectname文本框中输入工程名FileOperateTest,然后在Location文本框输入该工程名所在的文件夹。
如图13.1所示。
单击OK按钮。
在MFCAppWizard–Step1对话框中选择Dialogbased选项。
如图13.2所示。
最后单击Finish按钮。
创建一个基于对话框的工程完成。
图13.1选择工程类型和设置工程名以及工程路径
图13.2选择基本对话框选项
(2)在VC主界面的工作区中单击ResourceView选项卡,展开工作区中的Dialog项,双击IDD_FILEOPERATETEST_DIALOG,打开主对话框的资源编辑面板。
在该面板中加入8个按钮控件、一个文本框控件。
具体情况如表13.1所示。
表13.1对话框资源
控件ID
控件标题
关联变量
IDC_EDIT_DATA
无
m_strTextData
IDC_BUTTON_API_WRITE
使用API写
无
IDC_BUTTON_API_READ
使用API读
无
IDC_BUTTON_C_WRITE
使用C运行库写
无
IDC_BUTTON_C_READ
使用C运行库读
无
IDC_BUTTON_CFILE_WRITE
使用CFile写
无
IDC_BUTTON_CFILE_READ
使用CFile读
无
IDC_BUTTON_CSTDIOFILE_WRITE
CStdioFile写
无
IDC_BUTTON_CSTDIOFILE_READ
CStdioFile读
无
在主对话框资源编辑面板中双击“使用API打开”按钮,在弹出的AddMemberFunction对话框中单击OK按钮,完成增加该按钮的单击消息响应函数voidCFileOperateTestDlg:
:
OnButtonApiOpen(),其他按钮的单击响应函数的添加方式相同。
如图13.3所示:
图13.3添加按钮响应函数
(3)打开FileOperateTestDlg.cpp文件,编辑修改函数voidCFileOperateTestDlg:
: