登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

面包会有的

... ...

 
 
 

日志

 
 

VC读写INI文件  

2009-05-30 22:37:46|  分类: VC++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

GetPrivateProfileInt                       Retrieves   an   integer   associated   with  

                                                                a   key   in   the   specified   section   of   an  

                                                                initialization   file.    

GetPrivateProfileSection               Retrieves   all   the   keys   and   values    

                                                                for   the   specified   section   of   an    

                                                                initialization   file.    

GetPrivateProfileSectionNames     Retrieves   the   names   of   all   sections    

                                                                in   an   initialization   file.    

GetPrivateProfileString                 Retrieves   a   string   from   the    

                                                                specified   section   in   an    

                                                                initialization   file.    

GetPrivateProfileStruct                 Retrieves   the   data   associated   with   a    

                                                                key   in   the   specified   section   of   an    

                                                                initialization   file.    

GetProfileInt                                     Retrieves   an   integer   from   a   key   in    

                                                                the   specified   section   of   the   Win.ini    

                                                                file.    

GetProfileSection                             Retrieves   all   the   keys   and   values    

                                                                for   the   specified   section   of   the    

                                                                Win.ini   file.    

GetProfileString                               Retrieves   the   string   associated   with    

                                                                a   key   in   the   specified   section   of    

                                                                the   Win.ini   file.    

WritePrivateProfileSection           Replaces   the   keys   and   values   for   the    

                                                                specified   section   in   an    

                                                                initialization   file.    

WritePrivateProfileString             Copies   a   string   into   the   specified    

                                                                section   of   an   initialization   file.    

WritePrivateProfileStruct             Copies   data   into   a   key   in   the    

                                                                specified   section   of   an    

                                                                initialization   file.    

WriteProfileSection                         Replaces   the   contents   of   the    

                                                                specified   section   in   the   Win.ini    

                                                                file   with   specified   keys   and   values.    

WriteProfileString                           Copies   a   string   into   the   specified    

                                                                section   of   the   Win.ini   file.

在程序中经常要用到设置或者其他少量数据的存盘,以便程序在下一次执行的时候可以使用,比如说保存本次程序执行时窗口的位置、大小、一些用户设置的数据等等,在 Dos 下编程的时候,我们一般自己产生一个文件,由自己把这些数据写到文件中,然后在下一次执行的时候再读出来使用。在 Win32 编程中当然你也可以这样干,但 Windows 已经为我们提供了两种方便的办法,那就是使用注册表或者 ini 文件(Profile)来保存少量数据。本文中先介绍一下 .ini 文件的使用。

ini 文件是文本文件,中间的数据格式一般为:

[Section1 Name]

KeyName1=value1

KeyName2=value2

...

[Section2 Name]

KeyName1=value1

KeyName2=value2

ini 文件可以分为几个 Section,每个 Section 的名称用 [] 括起来,在一个 Section 中,可以有很多的 Key,每一个 Key 可以有一个值并占用一行,格式是 Key=value,Win32 对 ini 文件操作的 api 中,有一部分是对 win.ini 操作的,有一部分是对用户自定义的 ini 文件操作的。Win.in 和 system.ini 是Windows的两个非常重要的初始化文件,Windows将用户所作的选择以及各种变化的系统信息记录在这两个文件中。System.ini 描述了系统硬件的当前状态,Win.ini 文件则包含了Windows 系统运行环境的当前配置。由于 Win.ini 文件的重要性和常用性,Win32 中有专门对 Win.ini 进行操作的 api,它们是:

GetProfileInt - 从 Win.ini 文件的某个 Section 取得一个 key 的整数值,它的原形是:

GetProfileInt(

LPCTSTR lpAppName, // 指向包含 Section 名称的字符串地址

LPCTSTR lpKeyName, // 指向包含 Key 名称的字符串地址

INT nDefault // 如果 Key 值没有找到,则返回缺省的值是多少

);

如果 Key 值没有找到的话,返回值是 nDefault 指定的缺省值,如果 Key 中的值是负数,则返回 0,如果 Key 指定的是数字和字符串的混合,则返回数字部分的值,比如说 x=1234abcd,则返回 1234

GetProfileString - 从 Win.ini 文件的某个 Section 取得一个 key 的字符串,它的原形是:

GetProfileString(

LPCTSTR lpAppName, // 指向包含 Section 名称的字符串地址

LPCTSTR lpKeyName, // 指向包含 Key 名称的字符串地址

LPCTSTR lpDefault, // 如果 Key 值没有找到,则返回缺省的字符串的地址

LPTSTR lpReturnedString, // 返回字符串的缓冲区地址

DWORD nSize // 缓冲区的长度

);

返回的字符串在缓冲区内,返回的 eax 值是返回的字符串的长度(不包括尾部的0)

GetProfileSection - 从 Win.ini 文件中读出整个 Section 的内容,它的原形是:

GetProfileSection(

LPCTSTR lpAppName, // 指向包含 Section 名称的字符串地址

LPTSTR lpReturnedString, // 返回数据的缓冲区地址

DWORD nSize // 返回数据的缓冲区长度

);

WriteProfileSection - 将一个整个 Section 的值 写入 Win.ini 文件的指定 Section 中,它的原形是:

WriteProfileSection(

LPCTSTR lpAppName, // 指向包含 Section 名称的字符串地址

LPCTSTR lpString // 要写入的数据的地址

);

如果 Win.ini 没有指定的 Section,API 会新建立一个并写入数据,如果已经存在,则先删除原来 Seciton 中所有的 Key 值然后写入新的。

WriteProfileString - 将一个 Key 值写入 Win.ini 文件的指定 Section 中,它的原形是:

WriteProfileString(

LPCTSTR lpAppName, // 指向包含 Section 名称的字符串地址

LPCTSTR lpKeyName, // 指向包含 Key 名称的字符串地址

LPCTSTR lpString // 要写的字符串地址

);

如果 Win.ini 没有指定的 Section,API 会新建 Section,如果没有指定的 Key 则新建一个 Key 并写入数据,如果已经存在,则用字符串代替原来的值。

以上的 Api 是对 Win.ini 操作的,当然对于我们来说,用的更多的是在程序运行的目录中建立自己的 ini 文件,如果需要对自己的 ini 文件操作,就要用到另一组 Api,这一组 api 和上面的很象,只要把上面一组的 Profile 换成 PrivateProfile(私有的)就可以了,参数中也相应的多了一个 ini 文件名的参数。例如 GetPrivateProfileInt、GetPrivateProfileSection、WritePrivateProfileString 等等, 下面分别介绍:

GetPrivateProfileInt - 从 ini 文件的某个 Section 取得一个 key 的整数值,它的原形是:

GetPrivateProfileInt(

LPCTSTR lpAppName, // 指向包含 Section 名称的字符串地址

LPCTSTR lpKeyName, // 指向包含 Key 名称的字符串地址

INT nDefault // 如果 Key 值没有找到,则返回缺省的值是多少

LPCTSTR lpFileName // ini 文件的文件名

);

中间参数和返回值的定义和 GetProfileInt 是一样的。

GetPrivateProfileString - 从 ini 文件的某个 Section 取得一个 key 的字符串,它的原形是:

GetPrivateProfileString(

LPCTSTR lpAppName, // 指向包含 Section 名称的字符串地址

LPCTSTR lpKeyName, // 指向包含 Key 名称的字符串地址

LPCTSTR lpDefault, // 如果 Key 值没有找到,则返回缺省的字符串的地址

LPTSTR lpReturnedString, // 返回字符串的缓冲区地址

DWORD nSize // 缓冲区的长度

LPCTSTR lpFileName // ini 文件的文件名

);

GetPrivateProfileSection - 从 ini 文件中读出整个 Section 的内容,它的原形是:

GetPrivateProfileSection(

LPCTSTR lpAppName, // 指向包含 Section 名称的字符串地址

LPTSTR lpReturnedString, // 返回数据的缓冲区地址

DWORD nSize // 返回数据的缓冲区长度

LPCTSTR lpFileName // ini 文件的文件名

);

这个 api 可以读出整个 section 的内容,当你不知道 section 中有哪些 key 的时候,可以使用这个 api 将整个 section 读出后再处理。

GetPrivateProfileSectionNames - 从 ini 文件中获得 Section 的名称,它的原形是:

GetPrivateProfileSectionNames(

LPTSTR lpszReturnBuffer, // 返回数据的缓冲区地址

DWORD nSize // 返回数据的缓冲区长度

LPCTSTR lpFileName // ini 文件的文件名

);

如果 ini 中有两个 Section: [sec1] 和 [sec2],则返回的是 'sec1',0,'sec2',0,0 ,当你不知道 ini 中有哪些 section 的时候可以用这个 api 来获取名称

WritePrivateProfileSection - 将一个整个 Section 的内容入 ini 文件的指定 Section 中,它的原形是:

WritePrivateProfileSection(

LPCTSTR lpAppName, // 指向包含 Section 名称的字符串地址

LPCTSTR lpString // 要写入的数据的地址

LPCTSTR lpFileName // ini 文件的文件名

);

WritePrivateProfileString - 将一个 Key 值写入 ini 文件的指定 Section 中,它的原形是:

WritePrivateProfileString(

LPCTSTR lpAppName, // 指向包含 Section 名称的字符串地址

LPCTSTR lpKeyName, // 指向包含 Key 名称的字符串地址

LPCTSTR lpString // 要写的字符串地址

LPCTSTR lpFileName // ini 文件的文件名

);

如果 ini 中没有指定的 Section,API 会新建 Section,如果没有指定的 Key 则新建一个 Key 并写入数据,如果已经存在,则用字符串代替原来的值。当指定的 ini 也不存在的时候,API 会自动建立一个新的文件,所以使用 ini 的好处是我们不必为了保存少量的数据涉及到文件操作,就连查找文件是否存在的操作都不必要。

使用要点:

在我们实际使用的时候,用的最多的是 GetPrivateProfileString 和 WritePrivateProfileString,但在对自定义 ini 文件操作的时候要注意的是,如果 lpFileName 指定的文件没有路径的话,Api 会去 Windows 的安装目录去找而不会在当前目录找,但是每次用到 ini 函数要获取当前路径显然太麻烦了,这里有一个变通的办法,你只要在 ini 文件名前面加上 .\ 就可以了,比如说要对本目录下的 user.ini 操作,那么文件名就是 '.\user.ini' 这样显然比较方便。另外,当你要把一个 Key 清除的时候,可以使用把 lpString 指向一个空的字符串然后使用 WritePrivateProfileString。当你要把一个 section 的全部内容清空的时候,也不必把 key 一个个的清除,可以使用把 lpString 指向一个空的字符串然后使用 WritePrivateProfileSection。

--------------------------------

在我们写的程序当中,总有一些配置信息需要保存下来,以便完成程序的功能,最简单的办法就是将这些信息写入INI文件中,程序初始化时再读入.具体应用如下:

  一.将信息写入.INI文件中.

  1.所用的WINAPI函数原型为:

BOOL WritePrivateProfileString(

LPCTSTR lpAppName,

LPCTSTR lpKeyName,

LPCTSTR lpString,

LPCTSTR lpFileName

);  其中各参数的意义:

   LPCTSTR lpAppName 是INI文件中的一个字段名.

   LPCTSTR lpKeyName 是lpAppName下的一个键名,通俗讲就是变量名.

   LPCTSTR lpString 是键值,也就是变量的值,不过必须为LPCTSTR型或CString型的.

   LPCTSTR lpFileName 是完整的INI文件名.

  2.具体使用方法:设现有一名学生,需把他的姓名和年龄写入 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]

   

  3.要将学生的年龄保存下来,只需将整型的值变为字符型即可:

strTemp.Format("%d",nAge);

::WritePrivateProfileString("StudentInfo","Age",strTemp,

"c:\\stud\\student.ini");二.将信息从INI文件中读入程序中的变量.

  1.所用的WINAPI函数原型为:

DWORD GetPrivateProfileString(

LPCTSTR lpAppName,

LPCTSTR lpKeyName,

LPCTSTR lpDefault,

LPTSTR lpReturnedString,

DWORD nSize,

LPCTSTR lpFileName

);  其中各参数的意义:

   前二个参数与 WritePrivateProfileString中的意义一样.

   lpDefault : 如果INI文件中没有前两个参数指定的字段名或键名,则将此值赋给变量.

   lpReturnedString : 接收INI文件中的值的CString对象,即目的缓存器.

   nSize : 目的缓存器的大小.

   lpFileName : 是完整的INI文件名.

  2.具体使用方法:现要将上一步中写入的学生的信息读入程序中.

CString strStudName;

int nStudAge;

GetPrivateProfileString("StudentInfo","Name","默认姓名",

strStudName.GetBuffer(MAX_PATH),MAX_PATH,"c:\\stud\\student.ini");  执行后 strStudName 的值为:”张三”,若前两个参数有误,其值为:”默认姓名”.

  3.读入整型值要用另一个WINAPI函数:

UINT GetPrivateProfileInt(

LPCTSTR lpAppName,

LPCTSTR lpKeyName,

INT nDefault,

LPCTSTR lpFileName

);  这里的参数意义与上相同.使用方法如下:

nStudAge=GetPrivateProfileInt("StudentInfo","Age",10,

"c:\\stud\\student.ini");三.循环写入多个值,设现有一程序,要将最近使用的几个文件名保存下来,具体程序如下:

  1.写入:

CString strTemp,strTempA;

int i;

int nCount=6;

file://共有6个文件名需要保存

for(i=0;i {strTemp.Format("%d",i);

strTempA=文件名;

file://文件名可以从数组,列表框等处取得.

::WritePrivateProfileString("UseFileName","FileName"+strTemp,strTempA,

"c:\\usefile\\usefile.ini");

}

strTemp.Format("%d",nCount);

::WritePrivateProfileString("FileCount","Count",strTemp,

"c:\\usefile\\usefile.ini");

file://将文件总数写入,以便读出.  2.读出:

nCount=::GetPrivateProfileInt("FileCount","Count",0,

"c:\\usefile\\usefile.ini");

for(i=0;i {strTemp.Format("%d",i);

strTemp="FileName"+strTemp;

::GetPrivateProfileString("CurrentIni",strTemp,

"default.fil", strTempA.GetBuffer(MAX_PATH),MAX_PATH,

"c:\\usefile\\usefile.ini");

file://使用strTempA中的内容.

}  

补充四点:

   1.INI文件的路径必须完整,文件名前面的各级目录必须存在,否则写入不成功,该函数返回 FALSE 值.

   2.文件名的路径中必须为 \\ ,因为在VC++中, \\ 才表示一个 \ .

   3.也可将INI文件放在程序所在目录,此时 lpFileName 参数为: “.\\student.ini”.

//----------------------------------------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------

/*

类名:CIni

版本:v2.0

最后更新:

v2.0

梦小孩于2004年2月14日情人节

加入高级操作的功能

v1.0

梦小孩于2003年某日

一般操作完成

类描述:

本类可以于.ini文件进行操作

*/

文件 1:

#pragma once

#include "afxTempl.h"

class CIni

{

private:

CString m_strFileName;

public:

CIni(CString strFileName):m_strFileName(strFileName)

{

}

public:

//一般性操作:

BOOL SetFileName(LPCTSTR lpFileName); //设置文件名

CString GetFileName(void); //获得文件名

BOOL SetValue(LPCTSTR lpSection, LPCTSTR lpKey, LPCTSTR lpValue,bool bCreate=true); //设置键值,bCreate是指段名及键名未存在时,是否创建。

CString GetValue(LPCTSTR lpSection, LPCTSTR lpKey); //得到键值.

BOOL DelSection(LPCTSTR strSection); //删除段名

BOOL DelKey(LPCTSTR lpSection, LPCTSTR lpKey); //删除键名

public:

//高级操作:

int GetSections(CStringArray& arrSection); //枚举出全部的段名

int GetKeyValues(CStringArray& arrKey,CStringArray& arrValue,LPCTSTR lpSection); //枚举出一段内的全部键名及值

BOOL DelAllSections();

};

文件 2:

#include "StdAfx.h"

#include "ini.h"

#define MAX_ALLSECTIONS 2048 //全部的段名

#define MAX_SECTION 260 //一个段名长度

#define MAX_ALLKEYS 6000 //全部的键名

#define MAX_KEY 260 //一个键名长度

BOOL CIni::SetFileName(LPCTSTR lpFileName)

{

CFile file;

CFileStatus status;

if(!file.GetStatus(lpFileName,status))

return TRUE;

m_strFileName=lpFileName;

return FALSE;

}

CString CIni::GetFileName(void)

{

return m_strFileName;

}

BOOL CIni::SetValue(LPCTSTR lpSection, LPCTSTR lpKey, LPCTSTR lpValue,bool bCreate)

{

TCHAR lpTemp[MAX_PATH] ={0};

//以下if语句表示如果设置bCreate为false时,当没有这个键名时则返回TRUE(表示出错)

//!*&*none-value*&!* 这是个垃圾字符没有特别意义,这样乱写是防止凑巧相同。

if (!bCreate)

{

GetPrivateProfileString(lpSection,lpKey,"!*&*none-value*&!*",lpTemp,MAX_PATH,m_strFileName);

if(strcmp(lpTemp,"!*&*none-value*&!*")==0)

return TRUE;

}

if(WritePrivateProfileString(lpSection,lpKey,lpValue,m_strFileName))

return FALSE;

else

return GetLastError();

}

CString CIni::GetValue(LPCTSTR lpSection, LPCTSTR lpKey)

{

DWORD dValue;

TCHAR lpValue[MAX_PATH] ={0};

dValue=GetPrivateProfileString(lpSection,lpKey,"",lpValue,MAX_PATH,m_strFileName);

return lpValue;

}

BOOL CIni::DelSection(LPCTSTR lpSection)

{

if(WritePrivateProfileString(lpSection,NULL,NULL,m_strFileName))

return FALSE;

else

return GetLastError();

}

BOOL CIni::DelKey(LPCTSTR lpSection, LPCTSTR lpKey)

{

if(WritePrivateProfileString(lpSection,lpKey,NULL,m_strFileName))

return FALSE;

else

return GetLastError();

}

int CIni::GetSections(CStringArray& arrSection)

{

/*

本函数基础:

GetPrivateProfileSectionNames - 从 ini 文件中获得 Section 的名称

如果 ini 中有两个 Section: [sec1] 和 [sec2],则返回的是 'sec1',0,'sec2',0,0 ,当你不知道

ini 中有哪些 section 的时候可以用这个 api 来获取名称

*/

int i;

int iPos=0;

int iMaxCount;

TCHAR chSectionNames[MAX_ALLSECTIONS]={0}; //总的提出来的字符串

TCHAR chSection[MAX_SECTION]={0}; //存放一个段名。

GetPrivateProfileSectionNames(chSectionNames,MAX_ALLSECTIONS,m_strFileName);

//以下循环,截断到两个连续的0

for(i=0;i<MAX_ALLSECTIONS;i++)

{

if (chSectionNames==0)

if (chSectionNames==chSectionNames[i+1])

    break;

}

iMaxCount=i+1; //要多一个0号元素。即找出全部字符串的结束部分。

arrSection.RemoveAll();//清空原数组

for(i=0;i<iMaxCount;i++)

{

chSection[iPos++]=chSectionNames;

if(chSectionNames==0)

{

arrSection.Add(chSection);

memset(chSection,0,MAX_SECTION);

iPos=0;

}

}

return (int)arrSection.GetSize();

}

int CIni::GetKeyValues(CStringArray& arrKey,CStringArray& arrValue, LPCTSTR lpSection)

{

/*

本函数基础:

GetPrivateProfileSection- 从 ini 文件中获得一个Section的全部键名及值名

如果ini中有一个段,其下有 "段1=值1" "段2=值2",则返回的是 '段1=值1',0,'段2=值2',0,0 ,当你不知道

获得一个段中的所有键及值可以用这个。

*/

int i;

int iPos=0;

CString strKeyValue;

int iMaxCount;

TCHAR chKeyNames[MAX_ALLKEYS]={0}; //总的提出来的字符串

TCHAR chKey[MAX_KEY]={0}; //提出来的一个键名

GetPrivateProfileSection(lpSection,chKeyNames,MAX_ALLKEYS,m_strFileName);

for(i=0;i<MAX_ALLKEYS;i++)

{

if (chKeyNames==0)

if (chKeyNames==chKeyNames[i+1])

    break;

}

iMaxCount=i+1; //要多一个0号元素。即找出全部字符串的结束部分。

arrKey.RemoveAll();//清空原数组

arrValue.RemoveAll();

for(i=0;i<iMaxCount;i++)

{

chKey[iPos++]=chKeyNames;

if(chKeyNames==0)

{

strKeyValue=chKey;

arrKey.Add(strKeyValue.Left(strKeyValue.Find("=")));

arrValue.Add(strKeyValue.Mid(strKeyValue.Find("=")+1));

memset(chKey,0,MAX_KEY);

iPos=0;

}

}

return (int)arrKey.GetSize();

}

BOOL CIni::DelAllSections()

{

int nSection;

CStringArray arrSection;

nSection=GetSections(arrSection);

for(int i=0;i<nSection;i++)

{

if(DelSection(arrSection))

return GetLastError();

}

return FALSE;

}

使用方法:

CIni ini("c:\\a.ini");

int n;

/*获得值

TRACE("%s",ini.GetValue("段1","键1"));

*/

/*添加值

ini.SetValue("自定义段","键1","值");

ini.SetValue("自定义段2","键1","值",false);

*/

/*枚举全部段名

CStringArray arrSection;

n=ini.GetSections(arrSection);

for(int i=0;i<n;i++)

TRACE("%s\n",arrSection);

*/

/*枚举全部键名及值

CStringArray arrKey,arrValue;

n=ini.GetKeyValues(arrKey,arrValue,"段1");

for(int i=0;i<n;i++)

TRACE("键:%s\n值:%s\n",arrKey,arrValue);

*/

/*删除键值

ini.DelKey("段1","键1");

*/

/*删除段

ini.DelSection("段1");

*/

/*删除全部

ini.DelAllSections();

*/

  评论这张
 
阅读(2982)| 评论(0)

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018