在程序开发中,经常要保存一些配置参数,以便程序重新打开时读取出最后保存的配置信息,因为配置信息经常被用到,所有我这里将其封装成了一个类,以便以后复用,现在分享给大家。
特点:用一个标识来标记,可以保存值类型(double)型,可以保存一个字符串类型(wstring),因为double又可以强制转换成int或BOOL(bool)型,此类可以满足大部份的需求。
另外,已经重载了配置的方法,不仅可以使用配置立即生效,还可以立即保存到配置文件。
//Config.h
/*******************************************************************
* 作者: 他小的有
* 时间: 2016年7月30日23:00:00
* 描述: 配置的封装,可以将配置保存到文件和从文件读取
* 版本: 1.0
* 邮箱: 953546459@qq.com
* 博客: http://www.suchone.com
* 声明:Copyright (c) 2016 by Txdy, All Rights Reserved.
******************************************************************/
#ifndef _TXDY_CONFIG_H_
#define _TXDY_CONFIG_H_
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <algorithm>
#include <assert.h>
namespace Txdy
{
//配置参数
struct ConfigParam
{
int nIndex; //下标
double dValue; //值
std::wstring strMark; //描述
//默认的值
ConfigParam()
{
nIndex = 0;
dValue = 0.00;
strMark = _T("");
}
//重载运算符==
friend bool operator == (const ConfigParam& cp1, const ConfigParam& cp2)
{
return (cp1.nIndex == cp2.nIndex);
}
};
class CConfig
{
public:
CConfig(void);
~CConfig(void);
private:
std::vector <ConfigParam> m_vectorCP; //保存数据的容器
private:
//排序
static bool MinToMax(const ConfigParam pm1, const ConfigParam pm2); //从小到大排序
static bool MaxToMin(const ConfigParam pm1, const ConfigParam pm2); //从大到小排序
public:
//容器
void Sort(bool bMinToMax = true); //排序
void Swap(CConfig c); //交换
std::vector<ConfigParam>::iterator Begin(); //开始
std::vector<ConfigParam>::iterator End(); //结束
public:
//文件读写
bool Load(const std::string strFilePath); //加载文件
bool Save(const std::string strFilePath); //保存到文件
//参数设置/获取
void SetParam(const ConfigParam& cp); //设置参数
bool GetParam(ConfigParam *pConfig); //获取参数
//设置配置
void SetKey(int nIndex, double dValue, std::wstring strMark); //设置值和备注
void SetKey(int nIndex, double dValue); //设置值(没有描述)
void SetValue(int nIndex, double dValue); //设置值
void SetMark(int nIndex, std::wstring strMark); //设置备注
//设置配置并保存到文件
bool SetKey(int nIndex, double dValue, std::wstring strMark, const std::string strFilePath); //设置键值并保存到文件
bool SetValue(int nIndex, double dValue, const std::string strFilePath); //(重载)设置键值并保存到文件
bool SetMark(int nIndex, std::wstring strMark, const std::string strFilePath); //设置标志并保存到文件
//获取键值/描述
bool IsExist(int nIndex); //键值是否存在
double GetValue(int nIndex); //获取值
std::wstring GetMark(int nIndex); //获取描述
//其它
void Clear(); //清空
};
}
#endif//Config.cpp
#include "stdafx.h"
#include "Config.h"
namespace Txdy
{
CConfig::CConfig(void)
{
}
CConfig::~CConfig(void)
{
}
/* 功能:获取配置容器头
* 参数:无
* 返回值:返回容器迭代器的头指针
*/
std::vector<ConfigParam>::iterator CConfig::Begin()
{
return m_vectorCP.begin();
}
/* 功能:获取配置容器尾
* 参数:无
* 返回值:返回容器迭代器的尾指针
*/
std::vector<ConfigParam>::iterator CConfig::End()
{
return m_vectorCP.end();
}
/* 功能:对当前配置进行排序
* 参数:bMinToMax,是否从小到大(默认是)
* 返回值:无
*/
void CConfig::Sort(bool bMinToMax)
{
if (bMinToMax)
{
//从小到大
std::sort(m_vectorCP.begin(), m_vectorCP.end(), MinToMax);
}
else
{
//从大到小
std::sort(m_vectorCP.begin(), m_vectorCP.end(), MaxToMin);
}
}
/* 功能:交换配置
* 参数:sp,配置对象
* 返回值:无
*/
void CConfig::Swap(CConfig sp)
{
m_vectorCP.swap(sp.m_vectorCP);
}
/* 功能:从文件加载配置
* 参数:strFilePath,文件路径
* 返回值:如果保存成功,返回true,否则返回false
*/
bool CConfig::Load(const std::string strFilePath)
{
//清空之前的数据
Clear();
//从文件中读出
std::ifstream ifs(strFilePath, std::ios::binary);
if (!ifs.is_open())
{
return false;
}
//读出文件的内容
while (EOF != ifs.peek())
{
ConfigParam cp;
int nDataLen = 0;
ifs.read((char *)&nDataLen, sizeof(int)); //读长度标识
char *p = NULL, *pData = NULL;
p = pData = new char[nDataLen + 2];
ifs.read(pData, nDataLen);
pData[nDataLen] = '\0';
pData[nDataLen + 1] = '\0';
cp.nIndex = *(int *)pData; //下标
pData += sizeof(int);
cp.dValue = *(double *)pData; //值
pData += sizeof(double);
cp.strMark.append((TCHAR *)pData); //描述
m_vectorCP.push_back(cp);
if (NULL != p)
{
delete p;
p = NULL;
}
}
ifs.close();
return true;
}
/* 功能:将当前配置的信息保存到文件
* 参数:strFilePath,文件路径
* 返回值:如果保存成功,返回true,否则返回false
*/
bool CConfig::Save(const std::string strFilePath)
{
//打开文件
std::ofstream ofs(strFilePath, std::ios::binary);
if (!ofs.is_open())
{
return false;
}
//保存到文件
std::vector<ConfigParam>::iterator iterPM = m_vectorCP.begin();
while (iterPM != m_vectorCP.end())
{
size_t nStrSize = 2 * iterPM->strMark.size(); //字符串长度
size_t nTotalLen = sizeof(int) + sizeof(double) + nStrSize;
ofs.write((const char *)&nTotalLen, sizeof(int)); //总长度
ofs.write((const char *)&iterPM->nIndex, sizeof(int)); //标识
ofs.write((const char *)&iterPM->dValue, sizeof(double)); //值
ofs.write((const char *)iterPM->strMark.c_str(), nStrSize); //描述
iterPM++;
}
ofs.close();
return true;
}
/* 功能:设置参数,如果已经存在该配置则修改,否则添加该配置
* 参数:cp,配置参数结构体
* 返回值:无
*/
void CConfig::SetParam(const ConfigParam& cp)
{
//查找
std::vector<ConfigParam>::iterator iterCP = find(m_vectorCP.begin(), m_vectorCP.end(), cp);
if (iterCP != m_vectorCP.end())
{
//修改值和描述
iterCP->dValue = cp.dValue;
iterCP->strMark = cp.strMark;
}
else
{
//没有找到对应的下标,该下标还不存在,添加
m_vectorCP.push_back(cp);
}
}
/* 功能:获取配置
* 参数:pConfig,指向配置参数结构体的指针(备注:标识必须被指定,如果存在,返回时修改其它值和描述)
* 返回值:如果存在该配置,返回true,否则返回false
*/
bool CConfig::GetParam(ConfigParam *pConfig)
{
//查找
std::vector<ConfigParam>::iterator iterPM = find(m_vectorCP.begin(), m_vectorCP.end(), *pConfig);
if (iterPM == m_vectorCP.end())
{
//没有找到对应的下标
return false;
}
//查找到数据,附值
pConfig->dValue = iterPM->dValue;
pConfig->strMark = iterPM->strMark;
return true;
}
/* 功能:设置配置
* 参数:nIndex,配置标识
dValue,配置值
strMark,描述
* 返回值:无
*/
void CConfig::SetKey(int nIndex, double dValue, std::wstring strMark)
{
ConfigParam cp;
cp.nIndex = nIndex;
cp.dValue = dValue;
cp.strMark = strMark;
SetParam(cp);
}
/* 功能:重载设置配置(没有描述)
* 参数:nIndex,配置标识
dValue,配置值
* 返回值:无
*/
void CConfig::SetKey(int nIndex, double dValue)
{
SetKey(nIndex, dValue, _T(""));
}
/* 功能:设置值(不修改描述,如果有)
* 参数:nIndex,配置标识
dValue,配置值
* 返回值:无
* 备注:在调试模式下不存时报异常
*/
void CConfig::SetValue(int nIndex, double dValue)
{
ConfigParam cp;
cp.nIndex = nIndex;
std::vector<ConfigParam>::iterator iterPM = std::find(m_vectorCP.begin(), m_vectorCP.end(), cp);
if (iterPM != m_vectorCP.end())
{
//已经存在,修改
iterPM->dValue = dValue;
}
else
{
//不存在,错误
assert(0);
}
}
/* 功能:设置备注,如果存在标识,修改该标识的描述,如果不存在,添加此条标识,值被设为默认值
* 参数:nIndex,配置标识
strMark,备注
* 返回值:无
*/
void CConfig::SetMark(int nIndex, std::wstring strMark)
{
ConfigParam pm;
pm.nIndex = nIndex;
std::vector<ConfigParam>::iterator iterPM = find(m_vectorCP.begin(), m_vectorCP.end(), pm);
if (iterPM != m_vectorCP.end())
{
//已经存在,修改
iterPM->strMark = strMark;
}
else
{
//不存在,数值为默认值
SetKey(nIndex, 0.0, strMark);
}
}
/* 功能:设置配置,并保存到文件
* 参数:nIndex,标识
dValue,值
strMark,描述
strFilePath,文件路径
* 返回值:如果保存到文件成功,返回true,否则返回false
*/
bool CConfig::SetKey(int nIndex, double dValue, std::wstring strMark, const std::string strFilePath)
{
SetKey(nIndex, dValue, strMark);
return Save(strFilePath);
}
/* 功能:设置配置(没有描述),并保存到文件
* 参数:nIndex,标识
dValue,值
strFilePath,文件路径
* 返回值:如果保存到文件成功,返回true,否则返回false
*/
bool CConfig::SetValue(int nIndex, double dValue, const std::string strFilePath)
{
return SetKey(nIndex, dValue, _T(""), strFilePath);
}
/* 功能:设置配置(没有值),并保存到文件
* 参数:nIndex,标识
strMark,描述
strFilePath,文件路径
* 返回值:如果保存到文件成功,返回true,否则返回false
*/
bool CConfig::SetMark(int nIndex, std::wstring strMark, const std::string strFilePath)
{
return SetKey(nIndex, 0.0, strMark, strFilePath);
}
/* 功能:检测指定标识的配置是否存在
* 参数:nIndex,标识
* 返回值:如果存在返回true,否则返回false
*/
bool CConfig::IsExist(int nIndex)
{
for (auto iterPM = Begin(); iterPM != End(); iterPM++)
{
if (nIndex == iterPM->nIndex)
{
return true;
}
}
return false;
}
/* 功能:获取配置值
* 参数:nIndex,标识
* 返回值:配置值
* 备注:如果标识不存在,在调试调试模式下报异常,非调试模式时返回默认值
*/
double CConfig::GetValue(int nIndex)
{
ConfigParam pm;
pm.nIndex = nIndex;
std::vector<ConfigParam>::iterator iterPM = find(m_vectorCP.begin(), m_vectorCP.end(), pm);
if (iterPM == m_vectorCP.end())
{
assert(0);
return (0.0);
}
return iterPM->dValue;
}
/* 功能:获取配置描述
* 参数:nIndex,标识
* 返回值:配置值
* 备注:如果标识不存在,在调试调试模式下报异常,非调试模式时返回空描述
*/
std::wstring CConfig::GetMark(int nIndex)
{
ConfigParam cp;
cp.nIndex = nIndex;
std::vector<ConfigParam>::iterator iterPM = find(m_vectorCP.begin(), m_vectorCP.end(), cp);
if (iterPM == m_vectorCP.end())
{
assert(0);
return _T("");
}
return iterPM->strMark;
}
/* 功能:两个配置下标比较
* 参数:pm1,配置一
pm2,配置二
* 返回值:配置一小于配置二标识下标,返回true,否则返回false
*/
bool CConfig::MinToMax(const ConfigParam pm1, const ConfigParam pm2)
{
return (pm1.nIndex < pm2.nIndex);
}
/* 功能:两个配置下标比较
* 参数:pm1,配置一
pm2,配置二
* 返回值:配置一大于配置二标识下标,返回true,否则返回false
*/
bool CConfig::MaxToMin(const ConfigParam pm1, const ConfigParam pm2)
{
return (pm1.nIndex > pm2.nIndex);
}
/* 功能:清空配置容器
* 参数:无
* 返回值:无
*/
void CConfig::Clear()
{
m_vectorCP.clear();
}
}//使用实例
#include "stdafx.h"
#include <Windows.h>
#include "Core/Config.h"
//给配置取一个ID
//这里举例几个常用的场景
enum CFG
{
CFG_SPEED, //速度(double/int)
CFG_SAFE_CHECK, //安全检测(BOOL)
CFG_IP, //保存IP(string)
};
int _tmain(int argc, _TCHAR* argv[])
{
//保存配置的文件路径
std::string strFilePath = ("C:\\config.data");
//保存数据测试
//说明:保存到文件时有返回值,
Txdy::CConfig cfgSave;
cfgSave.SetKey(CFG_SPEED, 1000.0, _T("运动的速度")); //保存数值(描述可不写)
cfgSave.SetKey(CFG_SAFE_CHECK, TRUE); //保存布尔配置(忽略描述)
//保存字符串型配置(忽略数值)
//注意这里,最后一个参数为要保存配置到文件的路径,以上的的均有类型的重载,可以在参数生效的同时立即保存到文件
bool bRet = cfgSave.SetMark(CFG_IP, _T("192.168.0.1"), strFilePath);
if (bRet)
{
//保存到文件成功
}
else
{
//保存到文件失败
}
//读取数据测试
Txdy::CConfig cfgLoad;
bRet = cfgLoad.Load(strFilePath);
if (bRet)
{
//成功读取出数据
//速度
if (cfgLoad.IsExist(CFG_SPEED)) //调用IsExist(下标)可用于检测下标是否存在
{
//有速度的保存
double nSpeed = cfgLoad.GetValue(CFG_SPEED);
//其它操作
//...
}
//安全检测是否被选中
if (cfgLoad.IsExist(CFG_SAFE_CHECK))
{
BOOL bCheckSafe = static_cast<BOOL>(cfgLoad.GetValue(CFG_SAFE_CHECK));
//...
}
//IP
if (cfgLoad.IsExist(CFG_IP))
{
std::wstring strIP = cfgLoad.GetMark(CFG_IP);
//...
}
}
return 0;
}可扩展性强,如果因为软件的升级,需要新增新的配置,只需要在枚举里面新增配置的ID即可,不会影响到之前旧的配置。
顺便说了一下,为了防止与其它人的函数产生冲突,使用命名空间Txdy,如果项目不大,产生命名冲突的可能性较小,在实际使用的过程中可以 using namespace Txdy减少代码量。
源码SVN地址:http://code.taobao.org/svn/Txdy_CPP/
位于该目录下的 Examples/Config_Examle 文件夹中。
本站部分资源收集于网络,纯个人收藏,无商业用途,如有侵权请及时告知!