美文网首页
ini解析器

ini解析器

作者: _张鹏鹏_ | 来源:发表于2021-08-06 16:50 被阅读0次

    项目中需要用到解析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;
    }
    

    相关文章

      网友评论

          本文标题:ini解析器

          本文链接:https://www.haomeiwen.com/subject/szqivltx.html