配置文件读写:ConfigFile.hpp(支持无段名的配置项)

本文介绍了一个配置文件解析器的实现,支持无段名配置项,使用C++标准库进行字符串处理和文件操作,通过unordered_map存储配置数据,利用智能指针管理内存,实现了配置文件的读写、增删查改等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

支持无段名的配置项

#ifndef __CONFIGFILEINI_H_
#define __CONFIGFILEINI_H_
#include <unordered_map>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <memory>
#include <mutex>
#define CONF_DEFAULT_VALUE "NULL"
using namespace std;
//支持空域名

static string & trim_copy(string & s)
{
	if (s.empty())
	{
		return s;
	}
	s.erase(0, s.find_first_not_of(" "));
	s.erase(s.find_last_not_of(" ") + 1);
	return s;
}

class ConfigSection {
private:
	string m_sect_name;
	unordered_map<string, string> m_datas;

public:
	ConfigSection(const string & name = "")
		:m_sect_name(name)
	{
		m_datas.clear();
	}

public:
	void AddContext(const string& context)
	{
		size_t posEqual = context.find('=');
		if (posEqual == string::npos)
			return;

		string key = context.substr(0, posEqual); //读取从0位到“=”返回位的内容。
		key = trim_copy(key); //boost库去掉前后的空格

		string value = context.substr(posEqual + 1);//读取从“=”返回位下一位到最后的内容
		value = trim_copy(value);

		auto it = m_datas.find(key);
		if (it == m_datas.end())
		{
			m_datas.insert(make_pair(key, value));
		}
		else
		{
			m_datas[key] = value;
		}
	}

	void AddContext(const string& key, const string& value)
	{
		auto it = m_datas.find(key);
		if (it == m_datas.end())
		{
			m_datas.insert(make_pair(key, value));
		}
		else
		{
			m_datas[key] = value;
		}
	}

	void RemoveContext(const string & key)
	{
		auto it = m_datas.find(key);
		if (it != m_datas.end())
		{
			m_datas.erase(it);
		}
	}

	bool GetContext(const string & key, string & value)
	{
		auto it = m_datas.find(key);
		if (it != m_datas.end())
		{
			value = it->second;
			return true;
		}
		return false;
	}

	void Write2File(ofstream& stream)
	{
		if (!m_sect_name.empty())
		{
			stream << "[" << m_sect_name << "]" << endl;
		}
		for (auto &e : m_datas)
		{
			stream << e.first << " = " << e.second << endl;
		}
	}
};

class ConfigFile {

private:
	string m_file_name;
	std::mutex m_mutex;
	unordered_map<string, shared_ptr<ConfigSection>> m_sections;
	ConfigSection notitle_section;

private:
	void read_file(const string & file_name)
	{
		ifstream file(file_name.c_str());
		string line;
		std::shared_ptr<ConfigSection> temp_section(0);
		while (getline(file, line))
		{
			line = trim_copy(line);
			if (line.empty())
				continue;
			if (line[0] == '#')
				continue;

			if (is_sect_head(line))
			{
				string sect_head = line.substr(1, line.size() - 2);
				sect_head = trim_copy(sect_head);
				temp_section = std::shared_ptr<ConfigSection>(new ConfigSection(sect_head));
				m_sections.insert(make_pair(sect_head, temp_section));
			}
			else
			{
				if (temp_section == NULL)
				{
					notitle_section.AddContext(line);
				}
				else
				{
					temp_section->AddContext(line);
				}
			}
		}
		file.close();
	}

	inline bool is_sect_head(const string& context)
	{
		return (context.front() == '[' && context.back() == "]")
	}
public:
	ConfigFile(string fileName)
		:m_file_name(fileName)
		, notitle_section("")
	{
		read_file(fileName);
	}

	void Save2File(const string & fileName)
	{
		std::unique_lock<std::mutex> lk(m_mutex);
		ofstream stream;
		stream.open(fileName.c_str(), ios::out | ios::trunc);
		notitle_section.Write2File(stream);
		for (auto &e : m_sections)
		{
			e.second->Write2File(stream);
		}
		stream.close();
	}

	void Save2File() { Save2File(m_file_name); }

	string GetValue(string const& key, string const& sect_name = "", string const & default_value = CONF_DEFAULT_VALUE)
	{
		std::unique_lock<std::mutex> lk(m_mutex);
		string value;

		if (sect_name.empty())
		{
			if (notitle_section.GetContext(key, value))
			{
				return value;
			}
			return default_value;
		}

		auto it = m_sections.find(sect_name);
		if (it == m_sections.end())
		{
			return default_value;
		}
		if (it->second->GetContext(key, value))
		{
			return value;
		}
		return default_value;
	}

	void AddSection(const string& section)
	{
		unique_lock<std::mutex> lk(m_mutex); 
		auto it = m_sections.find(section);
		if (it == m_sections.end())
		{
			shared_ptr<ConfigSection> s = make_shared<ConfigSection>(section);
			m_sections.insert(make_pair(section, s));
		}
	}

	void RemoveSection(const string & section)
	{
		unique_lock<std::mutex> lk(m_mutex);
		auto it = m_sections.find(section);
		if (it != m_sections.end())
		{
			m_sections.erase(it);
		}
	}

	void AddContext(const string & key, const string & value, const string & section)
	{
		unique_lock<std::mutex> lk(m_mutex);
		if (section.empty())
		{
			notitle_section.AddContext(key, value);
			return;
		}

		shared_ptr<ConfigSection> temp_section;
		auto it = m_sections.find(section);
		if (it == m_sections.end())
		{
			shared_ptr<ConfigSection> s = make_shared<ConfigSection>(section); 
			m_sections.insert(make_pair(section, s));
			temp_section = s;
		}
		else
		{
			temp_section = it->second;
		}
		temp_section->AddContext(key, value);
	}

	void RemoveContext(const string & key, const string & section)
	{
		unique_lock<std::mutex> lk(m_mutex);
		if (section.empty())
		{
			notitle_section.RemoveContext(key);
			return;
		}

		auto it = m_sections.find(section);
		if (it == m_sections.end())
		{
			return;
		}

		shared_ptr<ConfigSection> temp_section = it->second;
		temp_section->RemoveContext(key);
	}
};
#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值