用Visual C++操作INI文件

来源:互联网 发布:企业oa软件 编辑:程序博客网 时间:2024/05/17 08:34
在我们写的程序当中,总有一些配置信息需要保存下来,以便完成程序的功能,最简单的办法就是将这些信息写入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] 
   Name=张三 

  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[i]==0) 
  if (chSectionNames[i]==chSectionNames[i+1]) 
  break; 

iMaxCount=i+1; //要多一个0号元素。即找出全部字符串的结束部分。 
arrSection.RemoveAll();//清空原数组 

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

 chSection[iPos++]=chSectionNames[i]; 
 if(chSectionNames[i]==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[i]==0) 
  if (chKeyNames[i]==chKeyNames[i+1]) 
  break; 

iMaxCount=i+1; //要多一个0号元素。即找出全部字符串的结束部分。 
arrKey.RemoveAll();//清空原数组 
arrValue.RemoveAll(); 

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

 chKey[iPos++]=chKeyNames[i]; 
 if(chKeyNames[i]==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[i])) 
  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[i]); 
*/ 

/*枚举全部键名及值 
CStringArray arrKey,arrValue; 
n=ini.GetKeyValues(arrKey,arrValue,"段1"); 
for(int i=0;i<n;i++) 
TRACE("键:%s/n值:%s/n",arrKey[i],arrValue[i]); 
*/ 

/*删除键值 
ini.DelKey("段1","键1"); 
*/ 

/*删除段 
ini.DelSection("段1"); 
*/ 

/*删除全部 
ini.DelAllSections(); 
*/