一、前言
我比较喜欢用ini后缀文件作为配置文件,因为它存储的数据结构看上起很清晰+数据读写很方便。
//ini数据存储结构
[section]
key=value
二、使用的函数
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib") //不要忘了加载库
//读取字符串的项
GetPrivateProfileString(section, key, defineValue, outValue, outValueLen, filePath);
//读取整数的项
GetPrivateProfileInt(section, key, defineValue, filePath);
//只能以字符串方式写入,若要写入整数得转绕下弯,手动转成字符串。
WritePrivateProfileString(section, key, value, filePath);
三、应用
1、提前准备: 创建ini文件+手写内容
吐槽:程序中没必要考虑文件没创建情况!!!软件发布时,配置文件是一起打包的。若程序代码中发现找不到配置文件,果断exit(0)吧。顺便在弹个提示框,“找不到配置文件xxx.ini,请确认你使用的是正版软件”。
2、撸代码
考虑到有多个配置文件,我写的这个类必须可以复用。面对不同的配置文件,差异之处在于文件名不同+一套{section+key}不同,而读取、设置数据方式都是相同的。于是,有了下边这样奇葩的设计。
2.1、类名
class FileIni
这是个基类!!!可以派生出"张三Ini",“李四Ini”。
2.2、成员函数
public:
//读取,让调用者知道是否成功。
bool read();
//设置本地+文件,考虑到配置文件很少写入,在这里顺便更新了文件数据
void set(string key, string value);
void set(string key, int value);
//返回的都是引用,因为数据都会存在成员变量中
const string& getString(string key);
const int& getInt(string key);
protected:
//在派生类构造函数中调用insertSectonKey设置section+key+默认值
virtual void initSectionKey() = 0;
void insertSectonKey(string section, string key, string defineValue);
void insertSectonKey(string section, string key, int defineValue);
纯虚函数initSectionKey是为了满足不同配置文件的差异化设置,文件名+一套{section+key}。实例化派生类后, 需要调用read()函数加载数据。调用set、get设置获取数据。设置获取数据略显麻烦,需要传入key值。所以我会把key值全部定义成宏。如: 井define IP_KEY_INI ”IP“。这样就避免每次手写,还容易写错!!!吐槽:虽然这样还是比直接把所有数据定义为成员变量麻烦。但为了复用啊,每新增一个配置文件,我只需派生一个基类,重写下initSectionKey就好了。
2.3、成员变量
string m_filePath; //ps ".\config\file.ini"
string m_errStr; //"err"
int m_errInt; //-1
map<string, string> m_keySection; //key,section
map<string, string> m_keyString; //key,字符串数据
map<string, int> m_keyInt; //key,整形数据
惊不惊讶,奇不奇怪。key对应section,key对应数据。这几个数据都要在initSectionKey中赋值。read()时会先调用initSectionKey,然后for(auto& iter : m_keyString ) 获取字符串数据,同理,获取整形数据。
2.4、完整代码
FileIni.h
#pragma once
#include <map>
using namespace std;
class FileIni
{
public:
FileIni();
~FileIni() { }
//读取,让调用者知道是否成功。
bool read();
//设置本地+文件
void set(string key, string value);
void set(string key, int value);
const string& getString(string key);
const int& getInt(string key);
protected:
//在派生类构造函数中调用insertSectonKey设置 section+key+默认值
virtual void initSectionKey() = 0;
void insertSectonKey(string section, string key, string defineValue);
void insertSectonKey(string section, string key, int defineValue);
private:
string m_filePath; //ps ".\config\file.ini"
string m_errStr;
int m_errInt;
map<string, string> m_keySection;
map<string, string> m_keyString;
map<string, int> m_keyInt;
};
FileIni.cpp
#include "FileIni.h"
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
FileIni::FileIni()
: m_filePath("")
, m_errStr("err")
, m_errInt(-1)
{}
bool FileIni::read()
{
m_keySection.clear();
m_keyString.clear();
m_keyInt.clear();
initSectionKey();
if (m_filePath.empty() || m_keySection.empty())
{
return false;
}
if (!PathFileExists(m_filePath.c_str()))
{
return false;
}
for (auto& iter : m_keyString)
{
const string& key = iter.first;
string& section = m_keySection[key];
string& define = iter.second;
char buff[1024] = { 0 };
GetPrivateProfileString(section.c_str(), key.c_str(), define.c_str(), buff, sizeof(buff), m_filePath.c_str());
iter.second = buff;
}
for (auto& iter : m_keyInt)
{
const string& key = iter.first;
string& section = m_keySection[key];
int& define = iter.second;
iter.second = GetPrivateProfileInt(section.c_str(), key.c_str(), define, m_filePath.c_str());
}
return true;
}
void FileIni::set(string key, string value)
{
auto iter = m_keyString.find(key);
if (iter != m_keyString.end())
{
iter->second = value;
string& section = m_keySection[key];
WritePrivateProfileString(section.c_str(), key.c_str(), value.c_str(), m_filePath.c_str());
}
}
void FileIni::set(string key, int value)
{
auto iter = m_keyInt.find(key);
if (iter != m_keyInt.end())
{
iter->second = value;
string& section = m_keySection[key];
char valueStr[64] = { 0 };
_itoa_s(value, valueStr, 10);
WritePrivateProfileString(section.c_str(), key.c_str(), valueStr, m_filePath.c_str());
}
}
const string& FileIni::getString(string key)
{
auto iter = m_keyString.find(key);
if (iter != m_keyString.end())
{
return iter->second;
}
return m_errStr;
}
const int& FileIni::getInt(string key)
{
auto iter = m_keyInt.find(key);
if (iter != m_keyInt.end())
{
return iter->second;
}
return m_errInt;
}
void FileIni::insertSectonKey(string section, string key, string defineValue)
{
m_keySection[key] = section;
m_keyString[key] = defineValue;
}
void FileIni::insertSectonKey(string section, string key, int defineValue)
{
m_keySection[key] = section;
m_keyInt[key] = defineValue;
}
积累生活的点点滴滴,不为你看到,只怕突然回忆。