我们在做软件的时候,有时候想软件启动的时候读取硬盘上的文件的一些参数,以供软件使用,也就是我们说的配置文件,配置文件可以是不同类型的文件,常见的格式有:.txt、.xml、.ini。当然也可以从数据库中读取配置文件,如果你不想使用这些,也可以自定义一种文件格式,这次我介绍的是最简单操作的.ini文件的一些常用操作。
一、ini文件介绍
INI文件是一种具有特定结构的文本文件,它的构成分为三部分,结构如下:
[Section1]
key 1 = value2
key 1 = value2
……
[Section2]
key 1 = value1
key 2 = value2
……
文件由若干个段落(section)组成,每个段落又分成若干个键(key)和值(value)。Windows系统自带的Win32的API函数GetPrivateProfileString()和WritePrivateProfileString()分别实现了对INI文件的读写操作,他们位于kernel32.dll下。
二、函数原型以及使用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //函数原型 BOOL WritePrivateProfileString( LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName); //其中 LPCTSTR lpAppName //是INI文件中的一个字段名. LPCTSTR lpKeyName //是lpAppName下的一个键名,通俗讲就是变量名. LPCTSTR lpString //是键值,也就是变量的值,不过必须为LPCTSTR型或CString型的. LPCTSTR lpFileName //是完整的INI文件名,如果没有指定完整路径名,则会在windows目录(默认)查找文件。如果文件没有找到,则函数会在windows目录创建它。 //例子:设现有一名学生,需把他的姓名和年龄写入 c:\stud\student.ini 文件中. CString strName,strTemp; int nAge; strName= "张三" ; nAge=12; ::WritePrivateProfileString( "StudentInfo" , "Name" ,strName, "c:\\stud\\student.ini" ); //此时c:\stud\student.ini文件中的内容如下: [StudentInfo] Name=张三 |
1 2 3 4 5 6 7 8 9 | //函数原型 DWORD GetPrivateProfileString(lpszSection, lpszKey, lpszDefault,lpReturnedString, cchReturnBuffer, lpszFile) //其中 LPCTSTR lpAppName, //配置文件的section名 LPCTSTR lpKeyName, //配置文件的key名 LPCTSTR lpDefault, //若配置文件中不存在指定的section或者key时返回的默认值 LPTSTR lpReturnedString, //接收INI文件中的值的CString对象,即目的缓存器 DWORD nSize, //缓存大小 LPCTSTR lpFileName //完整的配置文件路径 |
三、封装
不过我们在使用这两个函数时一般会对这两个函数进行简单的封装,使其用起来更加方便,比如说现在是对WritePrivateProfileString函数简单封装
1 2 3 4 5 6 7 8 | BOOL WriteString( LPCTSTR section, LPCTSTR key, char *stringtoadd, char *filename) { CHAR FilePath[255]; GetModuleFileName(NULL,FilePath,255); ( strrchr (FilePath, '\\' ))[1] = 0; strcat_s(FilePath,filename); return ::WritePrivateProfileString(section,key,stringtoadd,FilePath); } |
GetPrivateProfileString函数的封装
1 2 3 4 5 6 7 8 | DWORD ReadString( char *section, char * key, char stringtoread[], char * filename) { CHAR FilePath[255]; GetModuleFileName(NULL,FilePath,255); ( strrchr (FilePath, '\\' ))[1] = 0; strcat_s(FilePath,filename); return ::GetPrivateProfileString(section, key,NULL,stringtoread,255,FilePath); } |
要读取以及写数据的时候就可以直接调用WriteString以及ReadString了,减少了我们不必要的参数,更加有利于使用以及其他人理解。
四、读取一个字段的所有键与其值
有时候我们想一次读出一个.ini文件中某个字段下的所有值,那应该怎么办呢,下面介绍另外一个函数
1 2 3 4 5 6 7 | GetPrivateProfileSection //获取指定小节所有项名和值的一个列表 //返回值Long,装载到lpReturnedString缓冲区的字符数量。如缓冲区的容量不够大,不能容下所有信息,就返回nSize-2 //参数 类型及说明 lpAppName //String,欲获取的小节。注意这个字串不区分大小写 lpReturnedString //String,项和值字串的列表。每个字串都由一个NULL字符分隔,最后一个字串后面用两个NULL字符中止 nSize //Long,lpReturnedString缓冲区的大小。在windows系统中最大值为32767 lpFileName //String,初始化文件的名字。如没有指定完整路径名,windows就在Windows目录中查找文件 |
根据函数参数说明可以对读取到内容简单的分析一下就可以获取到所想要的字段内容,这个是读取某一字段的所有键,然后用vector保存起来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | //从配置文件中读取某一字段所有键和值 void ReadAllSectionValue(CString strSection, char * cValue, char *fileName) { CString strValue; CHAR FilePath[255]; GetModuleFileName(NULL,FilePath,255); ( strrchr (FilePath, '\\' ))[1] = 0; strcat_s(FilePath,fileName); GetPrivateProfileSection (strSection,cValue,32767,FilePath); } //从内存中获取该字段中所有的键 //这个函数是根据lpReturnedString 写出来的,需要理解一下 vector<CString> GetValueFromString( char * cValue) { vector<CString> vecTmp; if (cValue[0]== '\0' ) { return vecTmp; } for ( int iCurl=0; { CString strTmp; int iCnt=iCurl; for (;;iCnt++) { strTmp+=cValue[iCnt]; if (cValue[iCnt]== '\0' ) { break ; } } iCurl=iCnt+1; int iPos=strTmp.Find(_T( "=" )); strTmp=strTmp.Left(iPos-1); vecTmp.push_back(strTmp); if (cValue[iCurl]== '\0' ) { break ; } } return vecTmp; } vector ReadAllKes( char * cSection, char *strFileN) { //获取某一字段中所有的键,strFileN是配置文件的路径 char cValue[1024]; char cValue[1024]; vector <Cstring> vecValue; ReadAllSectionValue(cSection,cValue,strFileN); vecValue=GetValueFromString(cValue); return vecValue; } |
读懂了以上三个函数,对于.ini文件的所有操作基本上没什么大的问题了。