项目中需要用到解析ini格式的配置,手撸了一个:
static bool Startwith(const string&src, const string&str)
{
return src.compare(0, str.size(), str) == 0;
}
static void Trim(string &s) //去除字符两端空格
{
if (s.empty())
{
return;
}
s.erase(0, s.find_first_not_of(" "));
s.erase(s.find_last_not_of(" ") + 1);
}
class IniFileParser
{
public:
IniFileParser(const string& data)
{
istringstream strin(data);
string line;
while (getline(strin, line, '\n'))// 将字符以行形式存储;
{
Trim(line);
//默认以 '#', '-', '/', ';'开头的行为注释,过滤掉这些注释;
if (Startwith(line, "#") || Startwith(line, "-") || Startwith(line, "/") || Startwith(line, ";"))
continue;
lines.push_back(line);
}
}
string GetValue(const char* sectionName, const string&key)
{
UpdateContent(sectionName);
auto iter = content.find(key);
if (iter != content.end())
return iter->second;
return string();
}
private:
vector<string>::const_iterator FindSectionBeg(const char* sectionName)
{
string sectionTitle = string("[") + string(sectionName) + string("]");
return find(lines.begin(), lines.end(), sectionTitle);
}
vector<string>::const_iterator FindSectionEnd(const char* sectionName)
{
auto lineBeg = FindSectionBeg(sectionName);
if (lineBeg == lines.end())
return lines.end();
auto iter = lineBeg + 1; // 另起一行,找下一个section
for (; iter != lines.end(); ++iter)
{
const string& line = *iter;
if (Startwith(line, "["))
return iter;
}
// 没有找到下一个section,说明sectionName已经是最后一个section
return lines.end();
}
void UpdateContent(const char* sectionName)
{
auto lineBeg = FindSectionBeg(sectionName);
auto lineEnd = FindSectionEnd(sectionName);
FillContent(lineBeg, lineEnd);
}
void FillContent(vector<string>::const_iterator beg,
vector<string>::const_iterator end)
{
content.clear();
vector<string>::const_iterator iter = beg;
for (; iter != end; ++iter)
{
const string& line = *iter;
string::size_type pos = line.find("=");
if (pos == string::npos)
continue;
string key = line.substr(0, pos);
Trim(key);
string value = line.substr(pos + 1);
Trim(value);
content[key] = value;
}
}
private:
vector<string> lines; // 包含空行
map<string, string> content; // section的key value数据;
};
要解析的ini文件内容:
[mysql]
addr=127.0.0.1
user=root
psw=root
port=3306
dbname=db
以下是IniFileParser
使用demo:
int main()
{
string path = GetCfgFilePath(); // GetCfgFilePath自己实现
ifstream inputFile(path, ios::in);
if (!inputFile.is_open())
{
return 0;
}
std::string fileData((std::istreambuf_iterator<char>(inputFile)), std::istreambuf_iterator<char>());
IniFileParser iniParser(fileData);
string ip = iniParser.GetValue("mysql", "addr");
string userName = iniParser.GetValue("mysql", "user");
string password = iniParser.GetValue("mysql", "psw");
string strPort = iniParser.GetValue("mysql", "port");
string dbName = iniParser.GetValue("mysql", "dbname");
return 0;
}
网友评论