【C++】手搓读写properties文件源码
思路
properties文件实际上就是键值对的一种形式,用等号连接键和值。c++中和键值对最贴切的就是STL中的map了。所以我使用map作为properties的实际内存存储,同时为了方便使用,另外多一个set类型的字段记录所有的key。大致流程为:
1、逐行扫描文件内容;
2、过滤注释(#后面的为注释);
3、根据等号切割key和value;
4、保存key和value到map中;
需求:
1、当key没有值时:可以设定个默认值
2、读取文件时只有KEY没哟默认值会报错,添加一个默认值给该KEY
3、修改KEY的值时并保存到文件中
properties.h 头文件
cpp
/**
******************************************************************************
* @file : properties.h
* @author : CircleDBA
* @mail : [email protected]
* @blog : circle-dba.blog.csdn.net
* @date : 24-5-8
******************************************************************************
*/
#ifndef KINGBASEMANAGERTOOLS_PROPERTIES_H
#define KINGBASEMANAGERTOOLS_PROPERTIES_H
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <algorithm>
#include <sstream>
#include <vector>
#include <set>
#include <filesystem>
using namespace std;
namespace Circle {
class properties {
private:
string config_path;
map<string, string>* props = nullptr;
set<string>* keys = nullptr;
void trim(string& s);
vector<string> split(const string& str, char pattern);
public:
properties();
virtual ~properties();
void file(boost::filesystem::path path);
bool is_exists();
bool load(std::string defaultValue);
bool load(){load("None");};
set<string>* getKeys() const;
map<string, string>* getProps() const;
string getValue(const string& key,const string& defaultValue);
bool setValue(const string& key,const string& Value);
};
} // Circle
#endif //KINGBASEMANAGERTOOLS_PROPERTIES_H
properties.cpp 文件
cpp
/**
******************************************************************************
* @file : properties.cpp
* @author : CircleDBA
* @mail : [email protected]
* @blog : circle-dba.blog.csdn.net
* @date : 24-5-8
******************************************************************************
*/
#include "properties.h"
namespace fs = std::filesystem;
Circle::properties::properties() {
this->props = new map<string, string>();
this->keys = new set<string>();
}
Circle::properties::~properties() {
delete props;
delete keys;
}
//设置配置文件路径
void Circle::properties::file(std::string path){
this->config_path = path;
}
//判断配置文件是否存在
bool Circle::properties::is_exists(){
return fs::exists(this->config_path);
}
void Circle::properties::trim(string& s)
{
if (!s.empty())
{
s.erase(0, s.find_first_not_of(" "));
s.erase(s.find_last_not_of(" ") + 1);
}
}
vector<string> Circle::properties::split(const string& str, char pattern)
{
vector<string> res;
stringstream input(str);
string temp;
while (getline(input, temp, pattern))
{
res.push_back(temp);
}
return res;
}
bool Circle::properties::load(std::string defaultValue = "None"){
std::ifstream file(this->config_path);
std::string line;
while (getline(file, line)) {
trim(line);
//去空行
if (line.empty() || line == "\r" || line[0] == '#')
{
continue;
}
//处理等号后为空的配置
vector<string> res = split(line, '=');
if (res.size() < 2)
{
res[1] = defaultValue;
}
int t = res[1].find("#");
if (t != string::npos) {
res[1].erase(t);
}
for_each(res.begin(), res.end(), [=](string& s)mutable {
trim(s);
});
props->insert(make_pair(res[0], res[1]));
keys->insert(res[0]);
}
file.close();
}
set<string>* Circle::properties::getKeys() const {
return keys;
}
map<string, string>* Circle::properties::getProps() const {
return this->props;
}
string Circle::properties::getValue(const string& key,const string& defaultValue) {
if (props->find(key) == props->end())
{
return defaultValue;
}
string value =this->props->at(key);
return value;
}
bool Circle::properties::setValue(const string& key,const string& Value) {
if (props->find(key) == props->end())
{
this->props->insert(make_pair(key, Value));
}else{
props->at(key) = Value;
}
std::ofstream outFile(this->config_path);
for (const auto& pair : *props) {
outFile << pair.first << " = " << pair.second << std::endl;
}
return true;
}
example.properties 示例代码
cpp
key1 = value1
key3 = value3
key5 = aaa
log.key4 = value4
运行例子:
cpp
#include "properties.h"
main(){
std::string configPaht = "example.properties"
Circle::properties properties;
properties.file(configPaht);
//判断配置文件是否存在
if(properties.is_exists()){
//读取配置文件写入props,keys
properties.load();
//读取键值,如果不存在就返回默认值defaultValue
properties.getValue("key5","defaultValue");
//设置键值并写入文件
properties.setValue("key5","aaa");
}
}