他小的有

C++一个配置类的封装

在程序开发中,经常要保存一些配置参数,以便程序重新打开时读取出最后保存的配置信息,因为配置信息经常被用到,所有我这里将其封装成了一个类,以便以后复用,现在分享给大家。

特点:用一个标识来标记,可以保存值类型(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 文件夹中。

本站部分资源收集于网络,纯个人收藏,无商业用途,如有侵权请及时告知!

0
分享到:

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址