让你提前认识软件开发---学长的软件开发经验总结(12)配置文件读取及文件操作 【文章摘要】 在通信领域的软件开发项目中,C语言是主流的编程语言,而文件操作在其
第1部分 重新认识C语言
配置文件读取及文件操作
【文章摘要】
在通信领域的软件开发项目中,C语言是主流的编程语言,而文件操作在其中又占有很重要的地位。此外,为了体现产品的灵活性,可添加配置文件对某些重要的参数进行按需配置。这就要求程序能够准确读取到各个配置项的值。
本文以一个实际的小软件为例,介绍了C语言中配置文件的读取方法和重要的文件操作函数的使用方法,为相关软件开发项目提供了有益的参考。
【关键词】
C语言 文件函数
配置文件 操作
1.前言
在一般的软件项目中,常常需要用C语言对文件进行操作。在诸如对账之类的程序中,尤其如此。而C语言中有关文件操作的函数多达数十种,熟悉常用函数(如fopen、fclose、fgets、fread、fwrite等)的操作可以提高项目的编程效率,具有很现实的意义。
灵活性是优秀软件吸引用户的特性之一,为了体现软件的灵活性,可以将相关参数放置到一个配置文件中,用户可以根据需要进行设置。因此,C语言中的配置文件读取函数也值得关注。
本文以作者编写过的软件为例,对C语言中配置文件的读取和常用的文件操作函数的使用方法进行了详细的介绍。
2.本文使用的软件、文件操作函数和配置文件介绍
2.1本文使用的软件
本文使用的软件基于MFC实现,有一个用户操作的界面,如图1所示。
图1软件操作界面
在本软件中,三个主要按钮实现的功能为:
(1)“添加到输出框”按钮:从配置文件中读取相关信息,并输出到上面的空白框中(空白框的属性为LIST BOX)。
(2)“保存到文件”按钮:将从配置文件中读取到的信息保存到指定命名格式的文件中。
(3)“上传到FTP”按钮:将(2)中生成的文件上传到指定的FTP目录中。
2.2本文中使用的文件操作函数
本文使用的文件操作函数包括fopen、fwrite、fflush、fclose等,对它们的详细说明如下:
(1) fopen函数
作用:打开文件
表头文件:#include
定义函数:FILE *fopen(const char *path, const char *mode);
函数说明:参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代表着流形态。
mode有下列几种形态字符串:
r:打开只读文件,该文件必须存在。
r+:打开可读写的文件,该文件必须存在。
w:打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
w+:打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
a:以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
a+:以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
上述的形态字符串都可以再加一个b字符,如rb、w+b或ab+等组合,加入b字符用来告诉函数库打开的文件为二进制文件,而非纯文字文件。不过在POSIX系统,包含Linux都会忽略该字符。由fopen()所建立的新文件会具有
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)权限,此文件权限也会参考umask值。
返回值:文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败,则返回NULL,并把错误代码存在errno中。
附加说明:一般而言,打开文件后会作一些文件读取或写入的动作,若打开文件失败,接下来的读写动作也无法顺利进行,所以在fopen()后请作错误判断及处理。
(2) fwrite函数
作用:将数据写至文件流
表头文件:#include
定义函数:size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
函数说明:fwrite()用来将数据写入文件流中。参数stream为已打开的文件指针,参数ptr指向欲写入的数据地址,总共写入的字符数以参数size*nmemb来决定。fwrite()会返回实际写入的nmemb数目。
返回值:返回实际写入的nmemb数目。
(3) fflush函数
作用:更新缓冲区
表头文件:#include
定义函数:int fflush(FILE *stream);
函数说明:fflush()会强迫将缓冲区内的数据写回参数stream指定的文件中。如果参数stream为NULL,fflush()会将所有打开的文件数据更新。
返回值:成功返回0,失败返回EOF,错误代码存于errno中。
错误代码:EBADF参数stream指定的文件未被打开,或打开状态为只读。
(4) fclose函数
作用:关闭文件
表头文件:#include
定义函数:int fclose(FILE *stream);
函数说明:fclose()用来关闭先前fopen()打开的文件。此动作会让缓冲区内的数据写入文件中,并释放系统所提供的文件资源。
返回值:若关闭文件动作成功则返回0,有错误发生时则返回EOF并把错误代码存到errno中。
错误代码:EBADF表示参数stream非已打开的文件。
2.3本文中使用的配置文件
为了程序的正常运行,一般都会事先约定配置文件的命名及格式。在本文中,配置文件为Config.ini(ini为配置文件的常用后缀),文件中涉及到的配置项及注释如下:
;用于配置文件的本地存放路径
[General]
;文件的本地存放路径
LocalPath = D:\
;文件前缀
FilePrefix = EmployeeInfo
;文件后缀(形如txt,注意,不要加.)
FileSuffix = txt
;添加信息条数和具体信息(姓名+工号)
[EmployeeInfo]
;消息条数
MsgCount = 3
;消息内容
content1 = 00000001张三
content2 = 00000002李四
content3 = 00000003王五
; FTP信息,需按照实际情况来配置
[FTP]
; IP地址
IPAddr =
;用户名
UserName =
;密码
Password =
;传输方式:2 - BIN,1 - ASC
Mode = 1
;远端路径: FTP上传时存放文件的路径
FTPPath =
在配置文件中,将相关联的项放置在同一个大项中,用[]括起来(如上面的红色字体所示),各个小项的值直接放到等号的后面,注释部分用分号开头。
2.4本文中使用的读取配置操作函数
本文中使用的读取配置操作函数为GetPrivateProfileInt和GetPrivateProfileString,对它们的详细说明如下:
(1) GetPrivateProfileInt函数
作用:从配置文件中读取一个值,并将结果转换为整型数据后保存到变量中。
原型:UINT GetPrivateProfileInt(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName);
各参数的意义:
1) lpAppName:配置文件中的大项,用[]括起来的部分(如2.3节的红色字体所示)。
2) lpKeyName:各大项下小项的字段名称,如2.3节中General下的LocalPath。
3) nDefault:如果配置文件中没有这个配置项,那么代码中取的默认值。
4) lpFileName:配置文件名,如本文中的Config.ini。
举例:如本程序要获取MsgCount的值,则代码如下:
int iMsgCount = 0;
iMsgCount = GetPrivateProfileInt("EmployeeInfo", "MsgCount", 0, “Config.ini”);
(2) GetPrivateProfileString函数
作用:从配置文件中读取一个值,并将结果转换为字符串型数据后保存到变量中。
原型:DWORD GetPrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName);
各参数的意义:
1) lpAppName:配置文件中的大项,用[]括起来的部分(如2.3节的红色字体所示)。
2) lpKeyName:各大项下小项的字段名称,如2.3节中General下的LocalPath。
3) lpDefault:如果配置文件中没有这个配置项,那么代码中取的默认值。
4) lpReturnedString:代码中存放读取值的字符数组。
5) nSize:一般为lpReturnedString字符数组的大小。
6) lpFileName:配置文件名,如本文中的Config.ini。
举例:如本程序要获取FilePrefix的值,则代码如下:
char szFilePrefix[100] = {0};
GetPrivateProfileString("General", "FilePrefix", "EmployeeInfo", szFilePrefix, 100, strINIFILE);
2.5本文中使用的FTP操作函数
本文中使用的FTP操作函数为GetFtpConnection和PutFile,对它们的详细说明如下:
(1) GetFtpConnection函数
作用:连接FTP服务器。
原型:CFtpConnection* GetFtpConnection(LPCTSTR pstrServer, LPCTSTR pstrUserName, LPCTSTR pstrPassword, INTERNET_PORT nPort, BOOL bPassive);
各参数的意义:
1) pstrServer:服务名,即FTP服务器的IP地址。
2) pstrUserName:用户名,即登录FTP服务器的用户名。
3) pstrPassword:密码,即登录FTP服务器的密码。
4) nPort:端口号,该参数默认值为INTERNET_INVALID_PORT_NUMBER。
5) bPassive:该项的默认值为FALSE。
(2) PutFile函数
作用:FTP上传文件。
原型:BOOL PutFile(LPCTSTR pstrLocalFile, LPCTSTR pstrRemoteFile, DWORD dwFlags, DWORD_PTR dwContext);
各参数的意义:
1) pstrLocalFile:带存放路径的本地文件名。
2) pstrRemoteFile:带存放路径的远端文件名,即文件存放在FTP服务器的何处。
3) dwFlags:标识,该项取默认值FTP_TRANSFER_TYPE_BINARY。
4) dwContext:上下文标识,该项取默认值1。
3.程序流程
如2.1节所述,本程序主要实现三个功能,对应的配置文件如2.3节所示。每个功能的流程及相关说明如下:
3.1将配置文件中的数据添加到输出框
(1)该功能的流程图
如图2所示:
图2将配置文件中的数据添加到输出框流程图
(2)消息内容格式及异常考虑
本程序采用的消息内容格式为:工号姓名,如“00000001张三”,“00000001”表示工号,“张三”为姓名。在输出框里面,也是这样显示的。
本流程的异常情况主要考虑以下方面:
1) MsgCount项的值为空或0。
2)消息内容项(即content1、content2、content3等)为空或出现内容完全相同。
3)消息内容格式不正确,即不是“工号姓名”的格式。
4)工号相同(一般而言,员工工号不能相同)。
3.2将配置文件中的数据写入文件
(1)该功能的流程图
如图3所示:
图3将配置文件中的数据写入文件流程图
(2)文件命名、文件消息内容格式及异常考虑
文件命名格式为:FilePrefix时分秒.FileSuffix,如“EmployeeInfo155431.txt”。
文件消息内容格式与输出框格式一样,即“工号姓名”。
本流程考虑的异常情况与3.1节相同。
(3)有关文件操作函数的使用说明
1)对于fopen函数,由于要向文件中写入数据,因此“mode”参数可以采用“a”等,但不能采用“r”等表示只能读取的参数。
2)使用fwrite函数将数据写入文件,注意要在每条数据的最后面加上“\n”表示回车换行。
3)在写入数据完成之后,一定要加上fclose函数关闭文件,并且fclose函数一定要与fopen函数配对,且在使用fclose函数之后,要将文件指针置为null。
3.3将生成的文件上传到FTP服务器
(1)该功能的流程图
如图4所示:
图4将生成的文件上传到FTP服务器流程图
(2)有关FTP操作的说明
1)在执行操作之前,一定要确保FTP服务器的各项参数都配置正确。对于“Mode”项,1表示以ASC方式上传,2表示以二进制方式上传。
2) FTP操作的最大重试次数可根据需要进行设置,一般为3次。
4.对本软件进行测试
在程序运行起来之后,接下来的工作就是对之进行大量的测试,一定要对本程序涉及到的三个主要功能均进行充分的测试。
为了使得测试顺利进行,在运行本软件之前,需要将本软件和配置文件放在同一个文件夹的同一级目录下。当然,也可以在代码中设定特殊的配置文件存放目录。
对于“将配置文件中的数据添加到输出框”功能,检查输出框上面显示的内容是否和配置文件里面的信息一致,并对几种异常情况进行大量的测试。
对于“将配置文件中的数据写入文件”功能,检查文件命名是否符合要求、文件存放地址是否正确、文件里面的内容是否和输出框显示的信息一致,同时要对几种异常情况进行大量的测试。
对于“将生成的文件上传到FTP服务器”功能,检查FTP服务器上对应目录是否有文件存在,并对异常情况(如FTP信息配置不准确、本地文件不存在、远端路径不存在等)进行一定的测试。
5.总结
文件操作和配置文件在实际的软件开发项目中是很常见的,掌握C语言中常用文件操作函数的使用方法是对一个软件开发工程师的基本要求。
本文用实例来描述了C语言中常用的文件操作函数的用法及配置文件的使用方法。“冰冻三尺,非一日之寒”,要想熟练掌握C语言中常用文件操作函数及配置文件的用法,还需要我们不断地练习和总结。
(欢迎访问南邮BBS:http://bbs.njupt.edu.cn/)
(欢迎访问重邮BBS:http://bbs.cqupt.edu.cn/nForum/index)
(本系列文章每周更新两篇,敬请期待!本人新浪微博:http://weibo.com/zhouzxi?topnav=1&wvr=5,微信号:245924426,欢迎关注!)
让你提前认识软件开发---学长的软件开发经验总结(12),布布扣,bubuko.com