在程序开发中,经常要保存一些配置参数,以便程序重新打开时读取出最后保存的配置信息,因为配置信息经常被用到,所有我这里将其封装成了一个类,以便以后复用,现在分享给大家。
特点:用一个标识来标记,可以保存值类型(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 文件夹中。
本站部分资源收集于网络,纯个人收藏,无商业用途,如有侵权请及时告知!