c++ 解析INI配置文件

使用std库解析INI配置文件,可以区分“;”间隔的注释,缺点是如果有修改配置值,会把注释顶掉。

头文件:

#ifndef INI_PARSER_HPP
#define INI_PARSER_HPP

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cstdlib>
#include <map>
#include <string>
#include <mutex>

using namespace std;

class INIParser
{
private:
	map<string, map<string, string>> _map_ini;

	string & replace_all(string & str, const string & old_value, const string & new_value);
	string & replace_all_distinct(string & str, const string & old_value, const string & new_value);
public:
	~INIParser() { Clear(); }
    size_t GetSize() const { return _map_ini.size(); }
	string getStringFromFile(const string &file);
	bool ReadINI(const string & fileName);
	string GetString(const string & root, const string & key, const string & def = "") const;
	int GetInt(const string & root, const string & key, int def = 0) const;
	double GetDouble(const string & root, const string & key, double def = 0) const;
    bool GetBool(const string & root, const string & key, bool def = false) const;

	void SetValue(const string & root, const string & key, const string & value);
    void SetString(const string & root, const string & key, const string & value);
    void SetInt(const string & root, const string & key, int value);
    void SetDouble(const string & root, const string & key, double value);
    void SetBool(const string & root, const string & key, bool value);

	bool WriteINI(const string & path);	
	void Clear() { _map_ini.clear(); }
	void View();
};

#endif // INI_PARSER_HPP

cpp:

#include "ini_parser.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <stdio.h>

static void TrimString(string & str)
{
    str.erase(0, str.find_first_not_of(' '));
    str.erase(str.find_last_not_of(' ')+1);
}

string & INIParser::replace_all(string & str, const string & old_value, const string & new_value)
{
	while (true)
	{
		string::size_type pos = 0;
		pos = str.find(old_value);
		if (pos == string::npos) break;

		str.replace(pos, old_value.length(), new_value);
	}
	return str;
}

string & INIParser::replace_all_distinct(string & str, const string & old_value, const string & new_value)
{
	for (size_t pos = 0; pos != string::npos; pos += new_value.length())
	{
		pos = str.find(old_value, pos);
		if (pos == string::npos) break;
		
		str.replace(pos, old_value.length(), new_value);
	}
	return str;
}
string INIParser::getStringFromFile(const string &file)
{
	unsigned char* buffer = nullptr;
	size_t size = 0;
	size_t readsize;
	// Read the file from hardware
	FILE *fp = nullptr;
	fopen_s(&fp,file.c_str(), "rt");
	if (fp == nullptr)
	{
		return "";
	}
	fseek(fp, 0, SEEK_END);
	size = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	buffer = (unsigned char*)malloc(sizeof(unsigned char) * (size + 1));
	buffer[size] = '\0';

	readsize = fread(buffer, sizeof(unsigned char), size, fp);
	fclose(fp);

	if (readsize < size)
	{
		buffer[readsize] = '\0';
	}

	string str((char*)buffer);
	free(buffer);
	return str;
}
bool INIParser::ReadINI(const string & fileName)
{
	stringstream in_conf_file;
	try
	{
		string content = getStringFromFile(fileName);
		replace_all_distinct(content, "\r", "\n");
		if (content.empty()) return false;
		in_conf_file << content;
		string str_line = "";
		map<string, string> * kv_node = nullptr;
        size_t left_pos;
        size_t right_pos;
        size_t equal_div_pos;

		while (getline(in_conf_file, str_line))
		{
            if (str_line.empty()) continue;
			if ((string::npos != (left_pos = str_line.find("["))) &&
                (str_line.npos != (right_pos = str_line.find("]"))))
			{
				//配置头
				string root = str_line.substr(left_pos + 1, right_pos - left_pos - 1);
                TrimString(root);
                if (!root.empty())
                {
                    _map_ini[root] = map<string, string>{};
                    kv_node = &(_map_ini[root]);
                }
			}
			else if (string::npos != (equal_div_pos = str_line.find("=")))
			{
				//配置项,需要注意;为注释
				string key = str_line.substr(0, equal_div_pos);
				size_t notePos = str_line.find(";");
				string value;
				if (string::npos != notePos)
				{
					value = str_line.substr(equal_div_pos + 1, notePos - equal_div_pos - 1);
				}
				else
				{
					value = str_line.substr(equal_div_pos + 1, str_line.size() - 1);
				}
				TrimString(key);
				TrimString(value);
                if (kv_node != nullptr && !key.empty())
                {
                    (*kv_node)[key] = value;
                }
			}
		}
		return true;
	}
	catch (...)
	{
		return false;
	}
}


void INIParser::View()
{
	for (auto it = _map_ini.begin(); it != _map_ini.end(); ++it)
	{
		printf(it->first.c_str());
		printf("\n");
		for (auto vit = it->second.begin(); vit != it->second.end(); ++vit)
		{
			printf(vit->first.c_str());
			printf(" = ");
			printf(vit->second.c_str());
			printf("\n");
		}
	}
}


string INIParser::GetString(const string & root, const string & key, const string & def) const
{
	auto itr = _map_ini.find(root);
	if (itr == _map_ini.end()) return "";

	auto sub_itr = itr->second.find(key);
	if (sub_itr == itr->second.end()) return "";

	if (!(sub_itr->second).empty()) return sub_itr->second;
	return def;
}

int INIParser::GetInt(const string & root, const string & key, int def) const
{
	string str = GetString(root, key, "");
	if (str.empty()) return def;
	
	int res;
	try
	{
		istringstream is(str);
		is >> res;
	}
	catch(...)
	{
		res = def;
	}
	return res;
}

double INIParser::GetDouble(const string & root, const string & key, double def) const
{
	string str = GetString(root, key, "");
	if (str.empty()) return def;

	double res;
	try
	{
		istringstream is(str);
		is >> res;
	}
	catch(...)
	{
		res = def;
	}
	return res;
}

bool INIParser::GetBool(const string & root, const string & key, bool def) const
{
    string str = GetString(root, key, "");
    if (str.empty()) return def;

    if (str == "1") return true;
    std::transform(str.begin(), str.end(), str.begin(), ::tolower);
    if (str == "true") return true;
    return false;
}


bool INIParser::WriteINI(const string & path)
{
	ofstream out_conf_file(path.c_str());
	if (!out_conf_file) return false;

	for (auto itr = _map_ini.begin(); itr != _map_ini.end(); ++itr)
	{
		out_conf_file << "[" << itr->first << "]" << endl;
		for (map<string, string>::iterator sub_itr = itr->second.begin();
			sub_itr != itr->second.end(); ++sub_itr)
		{
			out_conf_file << sub_itr->first << "=" << sub_itr->second << endl;
		}
	}

	out_conf_file.close();
	out_conf_file.clear();
	return true;
}

void INIParser::SetValue(const string & root, const string & key, const string & value)
{
	auto itr = _map_ini.find(root);
	if (_map_ini.end() != itr)
	{
		map<string, string>::iterator it = itr->second.find(key);
		if (it != itr->second.end())
		{
			it->second = value;
		}
		else
		{
			itr->second[key] = value;
		}
	}
	else
	{
        map<string, string> m;
        m[key] = value;
		_map_ini[root] = std::move(m);
	}
}

void INIParser::SetString(const string & root, const string & key, const string & value)
{
    SetValue(root, key, value);
}

void INIParser::SetInt(const string & root, const string & key, int value)
{
    char buf[32];
    sprintf_s(buf, "%d", value);
    SetValue(root, key, buf);
}

void INIParser::SetDouble(const string & root, const string & key, double value)
{
    char buf[64];
	sprintf_s(buf, "%lf", value);
    SetValue(root, key, buf);
}

void INIParser::SetBool(const string & root, const string & key, bool value)
{
    if (value) SetValue(root, key, "1");
    else SetValue(root, key, "0");
}

测试:

int main()
{
	string file = "F:\\VersionConfig.ini";
	INIParser ini;
	printf(ini.getStringFromFile(file).c_str());
	printf("\n");
	ini.ReadINI(file);
	ini.View();
	system("pause");
    return 0;
}

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值