一、项目背景
在停车管理项目中不同道闸口的终端配置可能不同,如靠近居民楼的道闸终端LED的语音播报音量和靠近马路的道闸门口不同;不同终端道闸锁闸时间也可能不同,诸如此类放在数据库中,不同的终端在启动时必须先连接到数据库才能加载,远没有本地配置文件方便,也不如配置文件方便技术支持修改方便,对于此类本地化配置的参数需要进行提取改写到本地配置文件中。
二、ini配置文件
2.1 ini文件格式
ini文件简单,方便书写,但是只能表示二维数据结构;但相较于xml和json修改方便,也不容易修改出错,更适合做配置文件;xml和json在复杂的数据传输中更为合适。
2.2 ini文件解析器代码
这里以map作为内存缓存进行配置文件的读写,配置文件中的不同值需要以重载如下。
#pragma once
#include<string>
#include<map>
class Value
{
public:Value() = default;//重载不同类型的构造函数Value(bool);Value(int);Value(double);Value(std::string&);Value(const char*);//操作符重载 支持不同的类型直接=赋值给valueValue& operator=(bool);Value& operator=(int);Value& operator=(double);Value& operator=(std::string&);Value& operator=(const char*);//重载不同类型 便于Value直接赋值转换给不同类型值//类型转换没有返回值 因为返回值必为该类型operator bool();operator int();operator double();operator std::string();
private:std::string m_value;
};using Section = std::map<std::string, Value>;class iniFile
{public:iniFile() = default;bool load(const std::string&filename);Value &getValue(const std::string§ion, const::std::string&key);Section &operator[](const std::string§ion);void SetValue(const std::string§ion, const::std::string&key,const Value&value);bool hasKey(const std::string§ion, const::std::string&key);bool hasSection(const std::string§ion);void remove(const std::string§ion, const::std::string&key);void remove(const std::string§ion);std::string str();bool save(const std::string& name);void clear();private:std::string trim(std::string s);private:std::map<std::string, Section>m_mapSection;};
解析器实现代码
#include "iniFile.h"
#include<sstream>
#include<fstream>#define ConvertValue(value,m_value)\std::stringstream ss;\ss<<value;\ss>>m_value;Value::Value(bool value)
{m_value = value ? "true":"false";
}Value::Value(int value)
{*this = value;
}
Value::Value(double value)
{*this = value;
}
Value::Value(std::string&value)
{*this = value;
}
Value::Value(const char*value)
{*this = value;
}Value& Value::operator=(bool value)
{m_value = value ? "true" : "false";return *this;
}
Value& Value::operator=(int value)
{std::stringstream ss;ss << value;ss >> m_value;return *this;
}
Value& Value::operator=(double value)
{std::stringstream ss;ss << value;ss >> m_value;return *this;
}
Value& Value::operator=(std::string&value)
{m_value = value;return *this;
}
Value& Value::operator=(const char*value)
{m_value = value;return *this;
}//类型重载 当Value赋值给对应类型时默认调用该重载eg bool b = value;
Value::operator bool()
{return m_value == "true";
}Value::operator int()
{return std::atoi(m_value.c_str());
}
Value::operator double()
{return std::atof(m_value.c_str());
}
Value::operator std::string()
{return m_value;
}//ini文件操作
std::string iniFile::trim(std::string s)
{if (s.empty()){return s;}s.erase(0, s.find_first_not_of(" \n\r"));s.erase(s.find_last_not_of(" \n\r")+1);return s;
}
bool iniFile::load(const std::string&filename)
{if (filename.empty()){return false;}std::ifstream fin(filename);//filename 按行读取文件if (fin.fail()){return false;}std::string line, section;while (std::getline(fin, line)){line = trim(line);if (line == ""){continue;}if (line.at(0) == '['){int pos = line.find_first_of(']');section = trim(line.substr(1, pos - 1));m_mapSection[section] = Section();}else{int pos = line.find_first_of('=');std::string key = trim(line.substr(0, pos));std::string value = trim(line.substr(pos + 1, line.size() - pos));m_mapSection[section].insert(std::pair<std::string,std::string>(key, value));}}fin.close();return true;}Value & iniFile::getValue(const std::string§ion, const::std::string&key)
{return m_mapSection[section][key];
}
Section & iniFile::operator[](const std::string§ion)
{return m_mapSection[section];
}void iniFile::SetValue(const std::string§ion, const::std::string&key,const Value&value)
{m_mapSection[section][key] = value;
}
bool iniFile::hasKey(const std::string§ion, const::std::string&key)
{return hasSection(section) ? (m_mapSection[section].count(key)>0 ? true : false) : false;
}
bool iniFile::hasSection(const std::string§ion)
{return m_mapSection.count(section) > 0 ? true : false;
}void iniFile::remove(const std::string§ion, const::std::string&key)
{if (hasKey(section, key)){m_mapSection[section].erase(key);}
}
void iniFile::remove(const std::string§ion)
{if (hasSection(section)){m_mapSection.erase(section);}
}
void iniFile::clear()
{m_mapSection.clear();
}std::string iniFile::str()
{std::stringstream ss;for (auto it = m_mapSection.begin(); it != m_mapSection.end();++it){ss << "[" << it->first << "]" << std::endl;for (auto iter = it->second.begin(); iter != it->second.end(); ++iter){ss << iter->first << " = " <<std::string(iter->second)<< std::endl;}ss << std::endl;}return ss.str();
}bool iniFile::save(const std::string& name)
{std::ofstream fout(name);if (fout.fail()){return false;}fout << str();fout.close();return true;
}
测试代码
#include<iostream>
#include"iniFile.h"
using namespace std;int main()
{iniFile CfgFile;CfgFile.load("./Config.ini");std::string ip = CfgFile.getValue("Server", "ip");int port = CfgFile["Server"]["port"];CfgFile.SetValue("Server", "hostName", "wch");CfgFile.SetValue("User", "vipUser", "wch");CfgFile.SetValue("User", "CommonUser", "zhangsan");bool bC = CfgFile.hasKey("User", "CommonUser");CfgFile.remove("User", "CommonUser");bool bS = CfgFile.save("./modify.ini");return 0;
}
三、注册表的读写
3.1 项目背景
一般软件授权信息采用硬件加密好一点,但某些项目可能由于一些原因必须临时软授权供临时使用或体验,这种授权信息一般为加密信息,写在ini配置文件中,容易被无意间修改而导致软件解析授权信息失败从而无法使用,因此一般写在系统注册表中较好,不容易被修改。
3.2 QSetting
后面有空补一下