(读者可以点击这里获得源代码,注意解压后将boot.ini拷贝到E:\,以便程序运行找到文件)
头文件CfgData.h
// CfgData.h: interface for the CCfgData class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CFGDATA_H__A40CDB9A_0E44_49E6_A460_505D76BA6414__INCLUDED_)
#define AFX_CFGDATA_H__A40CDB9A_0E44_49E6_A460_505D76BA6414__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CCfgData
{
protected:
//组到配置数据的映射
CMapStringToPtr m_StrMapMap;
//当前组
CString m_strGroup;
public:
//构造配置数据
CCfgData();
//析构配置数据
virtual ~CCfgData();
//从文件加载配置数据
/*
参数: LPCTSTR strFileName 加载文件的名称
返回值:无
*/
void LoadCfgData(LPCTSTR strFileName);
//将配置数据保存到文件
/*
参数: LPCTSTR strFileName 保存文件的名称
返回值:成功返回TRUE 失败返回FALSE
*/
BOOL SaveCfgData(LPCTSTR strFileName);
//将配置数据保存到字符串
/*
参数: CString* pstr 要保存的字符串指针
返回值:成功返回TRUE 失败返回FALSE
*/
BOOL SaveToStr(CString* pstr);
//设置当前读取的组
/*
参数: 当前组名称
返回值:无
*/
void SetGroup(LPCTSTR strGroup);
//修改或者添加一条当前组中的数据
/*
参数: LPCTSTR strKey 要修改的数据的键值
LPCTSTR strValue要修改的数据的内容
返回值:
备注: 如果当前组在配置数据中存在,则修改或者添加该组对应键值的数据,如果当前组灾配置数据中不存在,则先创建该组
*/
BOOL SetData(LPCTSTR strKey,LPCTSTR strValue);
//得到当前组中对应键值中字符串类型的数据
/*
参数: LPCTSTR strKey 要得到的数据的键值
LPCTSTR strValue要得到的数据的内容
返回值:找到数据返回TRUE,否则返回FALSE
*/
virtual BOOL GetStrData(LPCTSTR strKey,CString &strValue);
//得到long型的数据
/*
参数: LPCTSTR strKey 要得到的数据的键值
long lValue 要得到的数据的值
返回值:找到数据返回TRUE,否则返回FALSE
*/
virtual BOOL GetLongData(LPCTSTR strKey,long &lValue);
protected:
//释放配置数据所占用的内存
/*
参数: 无
返回值:无
*/
void RemoveAll();
};
#endif // !defined(AFX_CFGDATA_H__A40CDB9A_0E44_49E6_A460_505D76BA6414__INCLUDED_)
源文件CfgData.cpp
// CfgData.cpp: implementation of the CCfgData class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CfgData.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//构造配置数据
CCfgData::CCfgData()
{
//初始化配置数据
m_strGroup="设置";
}
//析构配置数据
CCfgData::~CCfgData()
{
RemoveAll();
}
//释放配置数据所占用的内存
/*
参数: 无
返回值:无
*/
void CCfgData::RemoveAll()
{
POSITION pos=m_StrMapMap.GetStartPosition();
while(pos)
{
CMapStringToString* pStrMap;
CString str;
m_StrMapMap.GetNextAssoc(pos,str,(void*&)pStrMap);
if(pStrMap!=NULL)
{
pStrMap->RemoveAll();
//删除掉CString--> 指针映射中的指针
delete pStrMap;
}
}
m_StrMapMap.RemoveAll();
}
//从文件加载配置数据
/*
参数: LPCTSTR strFileName 加载文件的名称
返回值:无
*/
void CCfgData::LoadCfgData(LPCTSTR strFileName)
{
int iReadLen=0;
CString str[3];
int iState=0;//0:正在读入键值 1:正在读入内容 2:正在读入组
unsigned char ch; //正在读取的字符
//清空配置数据
RemoveAll();
CFile file;
file.Open(strFileName, CFile::modeRead);
file.Seek(0,CFile::begin);
str[0]="";//存放键值字符串
str[1]="";//存放内容字符串
str[2]="";//存放组字符串
//字符串到字符串的映射,保存键值和内容
CMapStringToString* pStrMap=NULL;
do
{
iReadLen=file.Read(&ch,1);
if(iReadLen!=0)
{
//处理中文
if(ch>0x80)//中文
{
str[iState]+=ch;
iReadLen=file.Read(&ch,1);
if(iReadLen!=0)
{
str[iState]+=ch;
}
}else
{
switch(ch)
{
//处理'['读入组字符串
case '[':
str[0].TrimLeft();
str[0].TrimRight();
str[1].TrimLeft();
str[1].TrimRight();
//确认键值和内容数据为空,否则可能是键值和内容中的符号
if(str[0]==""&&str[1]=="")
{
pStrMap=NULL;
iState=2;
str[2]="";
}else
{
str[iState]+=ch;
}
break;
//处理']'组字符串读入完毕
case ']':
//确认读入的是组的字符串数据
str[2].TrimLeft();
str[2].TrimRight();
if(iState==2&&str[2]!="")
{
iState=0;
//新建一个组下的键值-->内容映射,放入该组
pStrMap=new CMapStringToString;
m_StrMapMap.SetAt(str[2],pStrMap);
}else
{
str[iState]+=ch;
}
break;
case '=':
//开始读入内容
iState=1;
str[1]="";
break;
//处理回车和注释
case ';':
case 0x0d:
case 0x0a:
iState=0;
//键值非空
str[0].TrimLeft();
str[0].TrimRight();
str[1].TrimLeft();
str[1].TrimRight();
if(str[0]!=""&&pStrMap!=NULL)
{
pStrMap->SetAt((LPCTSTR)str[0],(LPCTSTR)str[1]);
}
//处理完清空数据
str[0]="";
str[1]="";
//注释的话继续读入直到文件结束或者碰到回车符号
if(ch==';')
{
while((iReadLen=file.Read(&ch,1))>0)
{
//如果遇到回车符号,终止,并且将当前位置退回
if(ch==0x0d||ch==0x0a)
{
file.Seek(-1,CFile::current);
break;
}
}
}
break;
default:
//普通字符,添加进入相应位置
str[iState]+=ch;
break;
}
}
}
}while(iReadLen!=0);
file.Close();
}
//设置当前读取的组
/*
参数: 当前组名称
返回值:无
*/
void CCfgData::SetGroup(LPCTSTR strGroup)
{
m_strGroup=strGroup;
}
//得到当前组中对应键值中字符串类型的数据
/*
参数: LPCTSTR strKey 要得到的数据的键值
LPCTSTR strValue要得到的数据的内容
返回值:找到数据返回TRUE,否则返回FALSE
*/
BOOL CCfgData::GetStrData(LPCTSTR strKey, CString &strValue)
{
CMapStringToString* pStrMap=NULL;
//寻找当前组
if(m_StrMapMap.Lookup(m_strGroup,(void*&)pStrMap))
{
if(pStrMap->Lookup(strKey,strValue))
return TRUE;
return FALSE;
}
return FALSE;
}
//得到long型的数据
/*
参数: LPCTSTR strKey 要得到的数据的键值
long lValue 要得到的数据的值
返回值:找到数据返回TRUE,否则返回FALSE
*/
BOOL CCfgData::GetLongData(LPCTSTR strKey, long &lValue)
{
CString str;
//得到对应的字符串数据
if(CCfgData::GetStrData(strKey, str))
{
lValue=atoi((LPCTSTR)str);
return TRUE;
}
return FALSE;
}
//修改或者添加一条当前组中的数据
/*
参数: LPCTSTR strKey 要修改的数据的键值
LPCTSTR strValue要修改的数据的内容
返回值:
备注: 如果当前组在配置数据中存在,则修改或者添加该组对应键值的数据,如果当前组灾配置数据中不存在,则先创建该组
*/
BOOL CCfgData::SetData(LPCTSTR strKey, LPCTSTR strValue)
{
CMapStringToString* pStrMap=NULL;
//如果存在该组,直接加入或者修改
if(m_StrMapMap.Lookup(m_strGroup,(void*&)pStrMap))
{
pStrMap->SetAt(strKey,strValue);
return TRUE;
}else
{
//创建该组
pStrMap=new CMapStringToString;
m_StrMapMap.SetAt(m_strGroup,pStrMap);
pStrMap->SetAt(strKey,strValue);
return TRUE;
}
}
//将配置数据保存到文件
/*
参数: LPCTSTR strFileName 保存文件的名称
返回值:成功返回TRUE 失败返回FALSE
*/
BOOL CCfgData::SaveCfgData(LPCTSTR strFileName)
{
CFile file;
if(!file.Open(strFileName,CFile::modeCreate|CFile::modeWrite))
return FALSE;
POSITION pos=m_StrMapMap.GetStartPosition();
char ch[6]="[]\r\n=";//特殊符号
CString str[3];
while(pos)
{
CMapStringToString* pStrMap;
m_StrMapMap.GetNextAssoc(pos,str[2],(void*&)pStrMap);
if(pStrMap!=NULL)
{
//写入组
file.Write(&ch[0],1);
file.Write((LPSTR)(LPCTSTR)str[2],str[2].GetLength());
file.Write(&ch[1],1);
file.Write(&ch[2],2);
POSITION pos1=pStrMap->GetStartPosition();
while(pos1)
{
//写入键值和内容
pStrMap->GetNextAssoc(pos1,str[0],str[1]);
file.Write((LPSTR)(LPCTSTR)str[0],str[0].GetLength());
file.Write(&ch[4],1);
file.Write((LPSTR)(LPCTSTR)str[1],str[1].GetLength());
file.Write(&ch[2],2);
}
}
}
file.Close();
return TRUE;
}
//将配置数据保存到字符串
/*
参数: CString* pstr 要保存的字符串指针
返回值:成功返回TRUE 失败返回FALSE
备注: 程序流程和上面基本相同,不同的保存进入字符串中
*/
BOOL CCfgData::SaveToStr(CString *pstr)
{
if(pstr==NULL)return FALSE;
*pstr="";
POSITION pos=m_StrMapMap.GetStartPosition();
CString str[4];
while(pos)
{
CMapStringToString* pStrMap;
m_StrMapMap.GetNextAssoc(pos,str[2],(void*&)pStrMap);
if(pStrMap!=NULL)
{
str[3]=*pstr;
pstr->Format("%s[%s]\r\n",str[3],str[2]);
POSITION pos1=pStrMap->GetStartPosition();
while(pos1)
{
pStrMap->GetNextAssoc(pos1,str[0],str[1]);
str[3]=*pstr;
pstr->Format("%s%s=%s\r\n",str[3],str[0],str[1]);
}
}
}
return TRUE;
}