C++ reads ini format configuration file

1. Background

ini is the program startup configuration file format in the early years. Some default parameters can be configured in this file. The format is:

;引号后面为注释
[group1]
name = group1
IP = 192.168.1.100
port = 7000
[group2]
name =  group2
IP = 192.168.1.101
port = 7002

[] Below the square brackets is a section, and the following value is indexed through the variable name. 

2. Code

Including the following header file, you can read and parse ini format files through this class

this.h

#ifndef INI_H_
#define INI_H_
#include <string>
#include <map>
#include<fstream>

namespace ini
{
	class iniReader
	{
	public:
		iniReader()
		{
		}
		~iniReader()
		{
		}
		bool ReadConfig(const std::string & filename)
		{
			settings_.clear();
			std::ifstream infile(filename.c_str());//构造默认调用open,所以可以不调用open
			//std::ifstream infile;
			//infile.open(filename.c_str());
			//bool ret = infile.is_open()
			if (!infile) {
				return false;
			}
			std::string line, key, value, section;
			std::map<std::string, std::string> k_v;
			std::map<std::string, std::map<std::string, std::string> >::iterator it;
			while (getline(infile, line))
			{
				if (AnalyseLine(line, section, key, value))
				{
					it = settings_.find(section);
					if (it != settings_.end())
					{
						k_v[key] = value;
						it->second = k_v;
					}
					else
					{
						k_v.clear();
						settings_.insert(std::make_pair(section, k_v));
					}
				}
				key.clear();
				value.clear();
			}
			infile.close();
			return true;
		}

		std::string ReadString(const char* section, const char* item, const char* default_value)
		{
			std::string tmp_s(section);
			std::string tmp_i(item);
			std::string def(default_value);
			std::map<std::string, std::string> k_v;
			std::map<std::string, std::string>::iterator it_item;
			std::map<std::string, std::map<std::string, std::string> >::iterator it;
			it = settings_.find(tmp_s);
			if (it == settings_.end())
			{
				//printf("111");
				return def;
			}
			k_v = it->second;
			it_item = k_v.find(tmp_i);
			if (it_item == k_v.end())
			{
				//printf("222");
				return def;
			}
			return it_item->second;
		}

		int ReadInt(const char* section, const char* item, const int& default_value)
		{
			std::string tmp_s(section);
			std::string tmp_i(item);
			std::map<std::string, std::string> k_v;
			std::map<std::string, std::string>::iterator it_item;
			std::map<std::string, std::map<std::string, std::string> >::iterator it;
			it = settings_.find(tmp_s);
			if (it == settings_.end())
			{
				return default_value;
			}
			k_v = it->second;
			it_item = k_v.find(tmp_i);
			if (it_item == k_v.end())
			{
				return default_value;
			}
			return atoi(it_item->second.c_str());
		}

		float ReadFloat(const char* section, const char* item, const float& default_value)
		{
			std::string tmp_s(section);
			std::string tmp_i(item);
			std::map<std::string, std::string> k_v;
			std::map<std::string, std::string>::iterator it_item;
			std::map<std::string, std::map<std::string, std::string> >::iterator it;
			it = settings_.find(tmp_s);
			if (it == settings_.end())
			{
				return default_value;
			}
			k_v = it->second;
			it_item = k_v.find(tmp_i);
			if (it_item == k_v.end())
			{
				return default_value;
			}
			return atof(it_item->second.c_str());
		}

	private:
		bool IsSpace(char c)
		{
			if (' ' == c || '\t' == c)
				return true;
			return false;
		}
		
		bool IsCommentChar(char c)
		{
			switch (c) 
			{
			case '#':
				return true;
			default:
				return false;
			}
		}

		void Trim(std::string & str)
		{
			if (str.empty())
			{
				return;
			}
			int i, start_pos, end_pos;
			for (i = 0; i < str.size(); ++i) {
				if (!IsSpace(str[i])) {
					break;
				}
			}
			if (i == str.size())
			{
				str = "";
				return;
			}
			start_pos = i;
			for (i = str.size() - 1; i >= 0; --i) {
				if (!IsSpace(str[i])) {
					break;
				}
			}
			end_pos = i;
			str = str.substr(start_pos, end_pos - start_pos + 1);
		}

		bool AnalyseLine(const std::string & line, std::string& section, std::string & key, std::string & value)
		{
			if (line.empty())
				return false;
			int start_pos = 0, end_pos = line.size() - 1, pos, s_startpos, s_endpos;
			if ((pos = line.find("#")) != -1)
			{
				if (0 == pos)
				{
					return false;
				}
				end_pos = pos - 1;
			}
			if (((s_startpos = line.find("[")) != -1) && ((s_endpos = line.find("]"))) != -1)
			{
				section = line.substr(s_startpos + 1, s_endpos - 1);
				return true;
			}
			std::string new_line = line.substr(start_pos, start_pos + 1 - end_pos);
			if ((pos = new_line.find('=')) == -1)
				return false;
			key = new_line.substr(0, pos);
			value = new_line.substr(pos + 1, end_pos + 1 - (pos + 1));
			Trim(key);
			if (key.empty()) {
				return false;
			}
			Trim(value);
			if ((pos = value.find("\r")) > 0)
			{
				value.replace(pos, 1, "");
			}
			if ((pos = value.find("\n")) > 0)
			{
				value.replace(pos, 1, "");
			}
			return true;
		}

	private:
		//std::map<std::string, std::string> settings_;
		std::map<std::string, std::map<std::string, std::string> >settings_;
	};
}
#endif

 test code

#include <iostream>
#include <fstream>
#include <cassert>
#include "ini.h"

int main() 
{

	ini::iniReader config;
	bool ret = config.ReadConfig("config.ini");
	if (ret == false) 
    {
		printf("ReadConfig is Error,Cfg=%s", "config.ini");
		return 1;
	}
	std::string HostName = config.ReadString("group1", "IP", "");
	int Port = config.ReadInt("group1", "port", 0);
	std::string UserName = config.ReadString("group1", "name", "");

	std::cout << "HostName=" << HostName << std::endl;
	std::cout << "Port=" << Port << std::endl;
	std::cout << "UserName=" << UserName << std::endl;

	return 0;
}

Guess you like

Origin blog.csdn.net/ljjjjjjjjjjj/article/details/125873100