在我们的程序设计中经常需要对一些参数进行配置,配置好后还要在下一次启动仍然有效,那么一个有效的可行办法就是使用ini文件,也就是Windows初始化文件来保存一些我们的设置,然后让程序启动的时候从这个ini文件中读取相关配置。我们需要做以下的工作。
1.创建此ini文件,Windows对ini文件的操作有专门的函数,我们经常用的就是WritePrivateProfileString()和GetPrivateProfileString()了。那么我们在程序的初始化时首先检查是否存在ini文件,如果不存在则创建一个默认的ini文件。
我们使用CFileFind类查找我们需要的ini文件是否存在,若不存在则创建一个。WritePrivateProfileString()当ini不存在时会自动创建一个ini文件在指定路径。
//向D盘写入程序数据库连接ini文件信息,默认设置如下
CFileFind finder; //查找是否存在ini文件,若不存在,则生成一个新的默认设置的ini文件,这样就保证了我们更改后的设置每次都可用
BOOL ifFind = finder.FindFile(_T("d:\\RoadDataManagerApp.ini"));
if( !ifFind )
{
::WritePrivateProfileStringW(_T("Database connection Info"),_T("IP"),_T("10.210.0.9"),_T("d:\\RoadDataManagerApp.ini"));
::WritePrivateProfileStringW(_T("Database connection Info"),_T("Database"),_T("RoadNetData"),_T("d:\\RoadDataManagerApp.ini"));
::WritePrivateProfileStringW(_T("Database connection Info"),_T("UID"),_T("sa"),_T("d:\\RoadDataManagerApp.ini"));
::WritePrivateProfileStringW(_T("Database connection Info"),_T("PWD"),_T("4814278"),_T("d:\\RoadDataManagerApp.ini"));
}
2.在刚才创建的ini文件中赋值,也就是WritePrivateProfileString()中所做的。
3.在需要用到ini文件的地方从ini文件中读取数据。例如:
::GetPrivateProfileStringW(_T("Database connection Info"),_T("IP"),_T("没找到IP信息"),m_strCurrentIP.GetBuffer(MAX_PATH),MAX_PATH,_T("d:\\RoadDataManagerApp.ini"));
::GetPrivateProfileStringW(_T("Database connection Info"),_T("Database"),_T("没找到数据库名信息"),m_strCurrentDBName.GetBuffer(MAX_PATH),MAX_PATH,_T("d:\\RoadDataManagerApp.ini"));
::GetPrivateProfileStringW(_T("Database connection Info"),_T("UID"),_T("没找到用户名信息"),m_strCurrentUID.GetBuffer(MAX_PATH),MAX_PATH,_T("d:\\RoadDataManagerApp.ini"));
::GetPrivateProfileStringW(_T("Database connection Info"),_T("PWD"),_T("没找到用户密码信息"),m_strCurrentPWD.GetBuffer(MAX_PATH),MAX_PATH,_T("d:\\RoadDataManagerApp.ini"));
//在这里必须ReleaseBuffer(),否则无法再后面进行字符串的连接
m_strCurrentIP.ReleaseBuffer();
m_strCurrentDBName.ReleaseBuffer();
m_strCurrentUID.ReleaseBuffer();
m_strCurrentPWD.ReleaseBuffer();
这样基本的操作我们就都知道了。下面详细说明对ini文件的各种操作。
INI文件简介
在我们写程序时,总有一些配置信息需要保存下来,以便在下一次启动程序完成初始化,这实际上是一种类持久化。将一些信息写入INI文件(initialization file)中,可完成简单的持久化支持。
Windows提供了API接口用于操作INI文件,其支持的INI文件格式一般如下:
===============================
[Section1]
Key11=value11
Key12=value12
[Section2]
Key21=value21
Key22=value22
...
[SectionN]
KeyN1=valueN1
KeyN2=valueN2
===============================
一般一个INI文件可有N个节,每节可有n个键名及值对应,每个键名及其值以等式形式占一行。
一般键的名称可任取,不过建议用有意义的字符及词构成。值一般可为整数和字符串,其它类型要进行转换。
常见的系统配置文件:
C:/boot.ini
C:/WINDOWS/win.ini
C:/WINDOWS/system.ini
C:/WINDOWS/desktop.ini
C:/WINDOWS/Resources/Themes/Windows Classic.theme
注意,字符串存贮在INI文件中时没有引号;key和value之间的等号前后不容空格;注释以分号“;”开头。
VC中操作INI文件的API
(1)操作系统配置文件Win.ini的函数:
函数名 |
功能 |
GetProfileSection |
读取win.ini中指定节lpAppName中所有键名及其值。lpReturnedString字符串形式如下: Key1=Value1/0Key2=Value2/0…KeyN=ValueN/0/0 |
GetProfileString |
读取win.ini中指定节lpAppName中键名为lpKeyName对应变量的字符串值。 |
GetProfileInt |
读取win.ini中指定节lpAppName中键名为lpKeyName对应变量的整数值。 |
|
|
WriteProfileSection |
写(替换)win.ini中指定节lpAppName中的键值。 lpString字符串形式同GetProfileSection中的lpReturnedString。 |
WriteProfileString |
写(替换)win.ini中指定节lpAppName中键名为lpKeyName对应变量的字符串值。 |
(2)操作用户自定义配置文件(PrivateProfile.ini)的函数:
函数名 |
功能 |
GetPrivateProfileSectionNames |
读取lpFileName指定的配置文件中所有的节名。lpszReturnBuffer字符串形式如下: Section1/0Section2/0…SectionN/0/0 |
GetPrivateProfileSection |
同GetProfileSection。 |
GetPrivateProfileString |
同GetProfileString。 |
GetPrivateProfileInt |
同GetProfileInt |
GetPrivateProfileStruct |
须同WritePrivateProfileStruct配套使用。 |
|
|
WritePrivateProfileSection |
同WriteProfileSection |
WritePrivateProfileString |
同WriteProfileString |
WritePrivateProfileStruct |
不常用。 |
注意:
(1)使用得最频繁的是 GetPrivateProfileString 和 WritePrivateProfileString,没有WriteProfileInt/WritePrivateProfileInt函数。
(2)Get系列读取节键值,如果文件路径有误或节键名不对则返回设定的默认值。
(3)访存自定义配置文件时,文件路径lpFileName必须完整,文件名前面的各级目录必须存在。如果lpFileName文件路径不存在,则函数返回FALSE,GetLastError() = ERROR_PATH_NOT_FOUND。如果路径正确,但是文件不存在,则该函数将先创建该文件。如果路径及文件存在,则在现有ini文件基础上进行读写。
如果 lpFileName 只指定文件名而没有路径的话,调用API将会去 Windows 的安装目录去查找而不会在当前目录查找。
(4)要对调用API的模块(exe)所在目录下进行配置文件操作,可使用形如“.//config.ini”的相对路径,注意转义符。
(5)调用WritePrivateProfileSection,若参数三 lpString为NULL,则可将对应section的全部内容清空;调用WritePrivateProfileString,若参数三 lpString为NULL,则可将对应key删除。
跨平台配置文件
INI文件本质是对文件和字符串的处理,因此在跨平台项目中的配置文件可以基于<stdio.h>中的标C文件FILE,然后实现像类似以上对节([Section])、键(Key)和值(Value)的字符串读写功能。
鉴于XML的树形描述层次结构性清晰,现在很多软件都大面积使用XML文件进行配置,如QQ的全局配置文件C:/Program Files/Tencent/QQ/gf-config.xml。java程序的配置文件基本都使用XML格式,C++中并没有操作XML文件的标准库。
在C/C++程序中要使用XML做为配置文件,涉及到XML的解析。Windows平台可使用MsXml对XML进行解析,参考《MsXml创建和解析XML示例》,跨平台可以考虑自己实现,或使用C++ BOOST正则表达式,或选择Free C or C++ XML Parser Libraries,如XmlParser、TinyXML、CMarkup、libxml等。
CIniFile类
以下提供对Windows操作INI文件的API的简单封装类CIniFile。
- // IniFile.h
- #ifndef __INIFILE_H__
- #define __INIFILE_H__
- class CIniFile
- {
- public:
- CIniFile();
- CIniFile(LPCTSTR szFileName);
- virtual ~CIniFile();
- public:
- // Attributes
- void SetFileName(LPCTSTR szFileName);
- public:
- // Operations
- BOOL SetProfileInt(LPCTSTR lpszSectionName, LPCTSTR lpszKeyName, int nKeyValue);
- BOOL SetProfileString(LPCTSTR lpszSectionName,