目录
一、项目背景
在停车管理项目中不同道闸口的终端配置可能不同,如靠近居民楼的道闸终端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*);
//操作符重载 支持不同的类型直接=赋值给value
Value& 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读写ini文件
头文件
#pragma once
#include <QSettings>
#include <QMap>
#include <QVariant>
#include <QMutex>
#include <string>
#include <vector>
using std::wstring;
using std::vector;
class ConfigUtil
{
public:
ConfigUtil(void);///<构造函数
~ConfigUtil(void);///<析构函数
ConfigUtil(ConfigUtil &&); //启用默认的移动构造函数
ConfigUtil& operator = (ConfigUtil&&);
ConfigUtil& operator = (const ConfigUtil& h) = delete;
ConfigUtil(const ConfigUtil& h) = delete;
static ConfigUtil *pmsIniInstance();
int openFile(const QString& file, QSettings::Format format);
int closeFile();
int sync();
QVariant getDefault(const QString& path);
int setDefault(const QString& path, const QVariant& v);
QVariant get(const QString& path, bool useDefault = true);
int set(const QString& path, const QVariant& v);
int writeDefaultToSetting();
private:
QSettings* _setting = nullptr;
QMap<QString, QVariant> _defaultSetting;
QMutex _mutex;
};
cpp实现文件
#include "QSettingsTest.h"
#include <QMutexLocker>
Q_GLOBAL_STATIC(ConfigUtil, configUtil)
ConfigUtil::ConfigUtil() :_mutex(QMutex::Recursive)
{
}
ConfigUtil* ConfigUtil::pmsIniInstance()
{
return configUtil();
}
ConfigUtil::~ConfigUtil()
{
closeFile();
}
ConfigUtil::ConfigUtil(ConfigUtil && other)
{
*this = std::move(other);
}
ConfigUtil& ConfigUtil::operator = (ConfigUtil&& other)
{
if (this == &other)
{
return *this;
}
QMutexLocker locker(&this->_mutex);
QMutexLocker locker2(&other._mutex);
this->_setting = other._setting;
other._setting = nullptr;
this->_defaultSetting = std::move(other._defaultSetting);
return *this;
}
int ConfigUtil::openFile(const QString& file, QSettings::Format format)
{
QMutexLocker locker(&_mutex);
QSettings* setting = new(std::nothrow) QSettings(file, format);
if (setting)
{
setting->setIniCodec("UTF-8");
closeFile();
_setting = setting;
_defaultSetting.clear();
return 0;
}
return -1;
}
int ConfigUtil::closeFile()
{
QMutexLocker locker(&_mutex);
if (_setting)
{
delete _setting;
_setting = nullptr;
_defaultSetting.clear();
}
return 0;
}
int ConfigUtil::sync()
{
QMutexLocker locker(&_mutex);
if (_setting)
{
_setting->sync();
return (_setting->status() != QSettings::AccessError) ? 0 : -1;
}
return -1;
}
QVariant ConfigUtil::getDefault(const QString& path)
{
QMutexLocker locker(&_mutex);
auto it = _defaultSetting.find(path);
if (it == _defaultSetting.end())
{
QVariant var;
return var;
}
return it.value();
}
int ConfigUtil::setDefault(const QString& path, const QVariant& v)
{
QMutexLocker locker(&_mutex);
_defaultSetting[path] = v;
return 0;
}
QVariant ConfigUtil::get(const QString& path, bool useDefault)
{
QMutexLocker locker(&_mutex);
if (!_setting)
{
return -1;
}
if (useDefault)
{
return _setting->value(path, _defaultSetting[path]);
//Returns the value for setting key. If the setting doesn't exist, returns defaultValue.
}
else
{
return _setting->value(path);
//If no default value is specified, a default QVariant is returned.
}
}
int ConfigUtil::set(const QString& path, const QVariant& v)
{
QMutexLocker locker(&_mutex);
if (!_setting)
{
return -1;
}
_setting->setValue(path, v);
return 0;
}
int ConfigUtil::writeDefaultToSetting()
{
QMutexLocker locker(&_mutex);
if (!_setting)
{
return -1;
}
auto it = _defaultSetting.begin();
auto list = _setting->allKeys();
for (it; it != _defaultSetting.end(); it++)
{
if (!list.contains(it.key()))
{
if (it.value().isValid() && (!it.value().isNull()))
{
_setting->setValue(it.key(), it.value());
}
}
}
return 0;
}
3.3 QSetting读写注册表
注册表读写参考之前博客:

1714

被折叠的 条评论
为什么被折叠?



