C++读写解析ini配置文件

71 篇文章 1 订阅
47 篇文章 5 订阅
1、简介
  • 支持解析ini文件
  • 支持修改、保存ini文件
  • 支持设置多个注释符,默认为“#”和’;’
  • 运行在Linux 下
2、代码

inifile.h

#ifndef INIFILE_H_
#define INIFILE_H_

#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
#include <iostream>

using std::string;
using std::vector;

//成功
#define RET_OK 0

// 没有找到匹配的]
#define ERR_UNMATCHED_BRACKETS 2

// 段为空
#define ERR_SECTION_EMPTY 3

// 段名已经存在
#define ERR_SECTION_ALREADY_EXISTS 4

// 解析key value失败
#define ERR_PARSE_KEY_VALUE_FAILED 5

// 打开文件失败
#define ERR_OPEN_FILE_FAILED 6

// 内存不足
#define ERR_NO_ENOUGH_MEMORY 7

// 没有找到对应的key
#define ERR_NOT_FOUND_KEY 8

// 没有找到对应的section
#define ERR_NOT_FOUND_SECTION 9


namespace inifile
{

//限定符号
const char delim[] = "\n";

//一条键值项
struct IniItem 
{
    string key;
    string value;
    string comment;  // 每个键的注释,都是指该行上方的内容
    string rightComment;
};

//一个节
struct IniSection 
{
    typedef vector<IniItem>::iterator IniItem_it;  // 定义一个迭代器,即指向键元素的指针
    IniItem_it begin() 
	{
        return items.begin();  // 段结构体的begin元素指向items的头指针
    }

    IniItem_it end() 
	{
        return items.end();  // 段结构体的end元素指向items的尾指针
    }

    string name;
    string comment;  // 每个段的注释,都是指该行上方的内容
    string rightComment;
    vector<IniItem> items;  // 键值项数组,一个段可以有多个键值,所有用vector来储存
};


//Ini配置文件类
class IniFile
{
 public:
    IniFile();
    ~IniFile() 
	{
        release();
    }

 public:
 
    /* 打开并解析一个名为fname的INI文件 */
    int Load(const string &fname);
	
		
	/*xcl添加:传入一个路径返回一个数组*/
	int Load(const string &filePath, vector<string> &retvalue);
	
		
    /* 将内容保存到当前文件 */
    int Save();
	
    /* 将内容另存到一个名为fname的文件 */
    int SaveAs(const string &fname);

    /* 获取section段第一个键为key的string值,成功返回0,否则返回错误码 */
    int GetStringValue(const string &section, const string &key, string *value);
	
    /* 获取section段第一个键为key的int值,成功返回0,否则返回错误码 */
    int GetIntValue(const string &section, const string &key, int *value);
	
    /* 获取section段第一个键为key的double值,成功返回0,否则返回错误码 */
    int GetDoubleValue(const string &section, const string &key, double *value);
	
    /* 获取section段第一个键为key的bool值,成功返回0,否则返回错误码 */
    int GetBoolValue(const string &section, const string &key, bool *value);
	
    /* 获取上方注释,如果key=""则获取段注释 */
    int GetComment(const string &section, const string &key, string *comment);
	
    /* 获取行尾注释,如果key=""则获取段的行尾注释 */
    int GetRightComment(const string &section, const string &key, string *rightComment);

    /* 获取section段第一个键为key的string值,成功返回获取的值,否则返回默认值 */
    void GetStringValueOrDefault(const string &section, const string &key, string *value, const string &defaultValue);
	
    /* 获取section段第一个键为key的int值,成功返回获取的值,否则返回默认值 */
    void GetIntValueOrDefault(const string &section, const string &key, int *value, int defaultValue);
	
    /* 获取section段第一个键为key的double值,成功返回获取的值,否则返回默认值 */
    void GetDoubleValueOrDefault(const string &section, const string &key, double *value, double defaultValue);
	
    /* 获取section段第一个键为key的bool值,成功返回获取的值,否则返回默认值 */
    void GetBoolValueOrDefault(const string &section, const string &key, bool *value, bool defaultValue);

    /* 获取section段所有键为key的值,并将值赋到values的vector中 */
    int GetValues(const string &section, const string &key, vector<string> *values);

    /* 获取section列表,并返回section个数 */
    int GetSections(vector<string> *sections);
	
    /* 获取section个数,至少存在一个空section */
    int GetSectionNum();
	
    /* 是否存在某个section */
    bool HasSection(const string &section);
	
    /* 获取指定section的所有ken=value信息 */
    IniSection *getSection(const string &section = "");
    
    /* 是否存在某个key */
    bool HasKey(const string &section, const string &key);

    /* 设置字符串值 */
    int SetStringValue(const string &section, const string &key, const string &value);
	
    /* 设置整形值 */
    int SetIntValue(const string &section, const string &key, int value);
	
    /* 设置浮点数值 */
    int SetDoubleValue(const string &section, const string &key, double value);
	
    /* 设置布尔值 */
    int SetBoolValue(const string &section, const string &key, bool value);
	
    /* 设置注释,如果key=""则设置段注释 */
    int SetComment(const string &section, const string &key, const string &comment);
	
    /* 设置行尾注释,如果key=""则设置段的行尾注释 */
    int SetRightComment(const string &section, const string &key, const string &rightComment);

    /* 删除段 */
    void DeleteSection(const string &section);
	
    /* 删除特定段的特定参数 */
    void DeleteKey(const string &section, const string &key);
	
    /*设置注释分隔符,默认为"#" */
    void SetCommentDelimiter(const string &delimiter);

    const string &GetErrMsg();
	
 public:
    /* 获取section段所有键为key的值,并将值赋到values的vector中,,将注释赋到comments的vector中 */
    int GetValues(const string &section, const string &key, vector<string> *value, vector<string> *comments);

    /* 同时设置值和注释 */
    int setValue(const string &section, const string &key, const string &value, const string &comment = "");

    /* 去掉str前面的c字符 */
    static void trimleft(string &str, char c = ' ');
	
    /* 去掉str后面的c字符 */
    static void trimright(string &str, char c = ' ');
	
    /* 去掉str前面和后面的空格符,Tab符等空白符 */
    static void trim(string &str);
    /* 将字符串str按分割符delim分割成多个子串 */
	
public:
    int UpdateSection(const string &cleanLine, const string &comment,
                      const string &rightComment, IniSection **section);
    int AddKeyValuePair(const string &cleanLine, const string &comment,
                        const string &rightComment, IniSection *section);

    void release();
    bool split(const string &str, const string &sep, string *left, string *right);
    bool IsCommentLine(const string &str);
    bool parse(const string &content, string *key, string *value);
    // for debug
    void print();

public:
    /* 获取section段第一个键为key的值,并将值赋到value中 */
    int getValue(const string &section, const string &key, string *value);
	
    /* 获取section段第一个键为key的值,并将值赋到value中,将注释赋到comment中 */
    int getValue(const string &section, const string &key, string *value, string *comment);

    bool StringCmpIgnoreCase(const string &str1, const string &str2);
    bool StartWith(const string &str, const string &prefix);

public:
    typedef vector<IniSection *>::iterator IniSection_it;
    vector<IniSection *> sections_vt;  // 用于存储段集合的vector容器
    string iniFilePath;
    string commentDelimiter;
    string errMsg;  // 保存出错时的错误信息
};

}  // endof namespace inifile

#endif  // INIFILE_H_


inifile.cpp

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <fstream>
#include "inifile.h"
using namespace std;

namespace inifile
{

// 构造函数,会初始化注释字符集合flags_(容器),目前只使用#和;作为注释前缀
IniFile::IniFile()
:commentDelimiter(";")     //commentDelimiter("#")
{
}

//解析一行数据,得到键、值
/* --------------------------------------------------------------------------*/
/**
 * @brief   parse
 *
 * @param   content 数据源指针
 * @param   key     键名
 * @param   value   键值
 * @param   c       分隔符
 *
 * @return  bool
 */
/* ----------------------------------------------------------------------------*/
bool IniFile::parse(const string &content, string *key, string *value)
{
    return split(content, "=", key, value);
}

int IniFile::UpdateSection(const string &cleanLine, const string &comment, const string &rightComment, IniSection **section)
{
    IniSection *newSection;
    // 查找右中括号
    size_t index = cleanLine.find_first_of(']');
    if (index == string::npos) {
        errMsg = string("no matched ] found");
        return ERR_UNMATCHED_BRACKETS;
    }

    int len = index - 1;
    // 若段名为空,继续下一行
    if (len <= 0) {
        errMsg = string("section name is empty");
        return ERR_SECTION_EMPTY;
    }

    // 取段名
    string s(cleanLine, 1, len);

    trim(s);

    //检查段是否已存在
    if (getSection(s) != NULL) {
        errMsg = string("section ") + s + string("already exist");
        return ERR_SECTION_ALREADY_EXISTS;
    }

    // 申请一个新段,由于map容器会自动排序,打乱原有顺序,因此改用vector存储(sections_vt)
    newSection = new IniSection();
    // 填充段名
    newSection->name = s;
    // 填充段开头的注释
    newSection->comment = comment;
    newSection->rightComment = rightComment;

    sections_vt.push_back(newSection);

    *section = newSection;

    return 0;
}

int IniFile::AddKeyValuePair(const string &cleanLine, const string &comment, const string &rightComment, IniSection *section)
{
    string key, value;

    if (!parse(cleanLine, &key, &value)) {
        errMsg = string("parse line failed:") + cleanLine;
        return ERR_PARSE_KEY_VALUE_FAILED;
    }

    IniItem item;
    item.key = key;
    item.value = value;
    item.comment = comment;
    item.rightComment = rightComment;

    section->items.push_back(item);

    return 0;
}

int IniFile::Load(const string &filePath)
{
    int err;
    string line;  // 带注释的行
    string cleanLine;  // 去掉注释后的行
    string comment;
    string rightComment;
    IniSection *currSection = NULL;  // 初始化一个字段指针

    release();

    iniFilePath = filePath;
    std::ifstream ifs(iniFilePath);
    if (!ifs.is_open()) {
        errMsg = string("open") +iniFilePath+ string(" file failed");
        return ERR_OPEN_FILE_FAILED;
    }

    //增加默认段,即 无名段""
    currSection = new IniSection();
    currSection->name = "";
    sections_vt.push_back(currSection);

    // 每次读取一行内容到line
    while (std::getline(ifs, line)) {
        trim(line);

        // step 0,空行处理,如果长度为0,说明是空行,添加到comment,当作是注释的一部分
        if (line.length() <= 0) {
            comment += delim;
            continue;
        }

        // step 1
        // 如果行首不是注释,查找行尾是否存在注释
        // 如果该行以注释开头,添加到comment,跳过当前循环,continue
        if (IsCommentLine(line)) {
            comment += line + delim;
            continue;
        }

        // 如果行首不是注释,查找行尾是否存在注释,若存在,切割该行,将注释内容添加到rightComment
        split(line, commentDelimiter, &cleanLine, &rightComment);

        // step 2,判断line内容是否为段或键
        //段开头查找 [
        if (cleanLine[0] == '[') {
            err = UpdateSection(cleanLine, comment, rightComment, &currSection);
        } else {
            // 如果该行是键值,添加到section段的items容器
             err = AddKeyValuePair(cleanLine, comment, rightComment, currSection);
        }

        if (err != 0) {
            ifs.close();
            return err;
        }

        // comment清零
        comment = "";
        rightComment = "";
    }

    ifs.close();

    return 0;
}



/*xcl添加: 传入一个路径返回一个数组*/
int IniFile::Load(const string &filePath, vector<string> &retvalue)
{
    int err;
    string line;  // 带注释的行
    string cleanLine;  // 去掉注释后的行
    string comment;
    string rightComment;
    IniSection *currSection = NULL;  // 初始化一个字段指针

    release();

    iniFilePath = filePath;
    std::ifstream ifs(iniFilePath);
    if (!ifs.is_open()) 
	{
        errMsg = string("open") +iniFilePath+ string(" file failed");
        return ERR_OPEN_FILE_FAILED;
    }

    //增加默认段,即 无名段""
    currSection = new IniSection();
    currSection->name = "";
    sections_vt.push_back(currSection);

    //每次读取一行内容到line
    while (std::getline(ifs, line)) 
	{
        trim(line);//trim,整理一行字符串,去掉首尾空格

        // step 0,空行处理,如果长度为0,说明是空行,添加到comment,当作是注释的一部分
        if (line.length() <= 0) 
		{
            comment += delim;
            continue;
        }

        // step 1
        // 如果行首不是注释,查找行尾是否存在注释
        // 如果该行以注释开头,添加到comment,跳过当前循环,continue
        if (IsCommentLine(line)) 
		{
            comment += line + delim;
            continue;
        }

        // 如果行首不是注释,查找行尾是否存在注释,若存在,切割该行,将注释内容添加到rightComment
        split(line, commentDelimiter, &cleanLine, &rightComment);

        // step 2,判断line内容是否为段或键
        //段开头查找 [
        if (cleanLine[0] == '[') 
		{
            err = UpdateSection(cleanLine, comment, rightComment, &currSection);
        } 
		else 
		{
            // 如果该行是键值,添加到section段的items容器
             err = AddKeyValuePair(cleanLine, comment, rightComment, currSection);
        }

        if (err != 0) 
		{
            ifs.close();
            return err;
        }

        // comment清零
        comment = "";
        rightComment = "";
    }
	
	
	//把=右边的值放到一个数组里边
	for(int i = 0; i < currSection->items.size(); i++)
	{
		retvalue.push_back(currSection->items[i].value);
	}
		

    ifs.close();

    return 0;
}




int IniFile::Save()
{
    return SaveAs(iniFilePath);
}

int IniFile::SaveAs(const string &filePath)
{
    string data = "";

    /* 载入section数据 */
    for (IniSection_it sect = sections_vt.begin(); sect != sections_vt.end(); ++sect) {
        if ((*sect)->comment != "") {
            data += (*sect)->comment;
        }

        if ((*sect)->name != "") {
            data += string("[") + (*sect)->name + string("]");
            data += delim;
        }

        if ((*sect)->rightComment != "") {
            data += " " + commentDelimiter +(*sect)->rightComment;
        }

        /* 载入item数据 */
        for (IniSection::IniItem_it item = (*sect)->items.begin(); item != (*sect)->items.end(); ++item) {
            if (item->comment != "") {
                data += item->comment;
                if (data[data.length()-1] != '\n') {
                    data += delim;
                }
            }

            data += item->key + "=" + item->value;

            if (item->rightComment != "") {
                data += " " + commentDelimiter + item->rightComment;
            }

            if (data[data.length()-1] != '\n') {
                data += delim;
            }
        }
    }

	cout<<data<<endl;

   // std::ofstream ofs(filePath);
    std::ofstream ofs;
	ofs.open(filePath, ios::out|ios::trunc);
	if(ofs.is_open()==false)  //判断文件是否打开成功,is_open 返回值是一个bool类型
    {
       cout<<"文件打开失败!"<<endl;
    }
    ofs << data;
    ofs.close();
	
	cout<<"写文件结束";
	
    return 0;
}

IniSection *IniFile::getSection(const string &section /*=""*/)
{
    for (IniSection_it it = sections_vt.begin(); it != sections_vt.end(); ++it) {
        if ((*it)->name == section) {
            return *it;
        }
    }

    return NULL;
}

int IniFile::GetSections(vector<string> *sections)
{
    for (IniSection_it it = sections_vt.begin(); it != sections_vt.end(); ++it) {
        sections->push_back((*it)->name);
    }

    return sections->size();
}

int IniFile::GetSectionNum()
{
    return sections_vt.size();
}

int IniFile::GetStringValue(const string &section, const string &key, string *value)
{
    return getValue(section, key, value);
}

int IniFile::GetIntValue(const string &section, const string &key, int *intValue)
{
    int err;
    string strValue;

    err = getValue(section, key, &strValue);

    *intValue = atoi(strValue.c_str());

    return err;
}

int IniFile::GetDoubleValue(const string &section, const string &key, double *value)
{
    int err;
    string strValue;

    err = getValue(section, key, &strValue);

    *value = atof(strValue.c_str());

    return err;
}

int IniFile::GetBoolValue(const string &section, const string &key, bool *value)
{
    int err;
    string strValue;

    err = getValue(section, key, &strValue);

    if (StringCmpIgnoreCase(strValue, "true") || StringCmpIgnoreCase(strValue, "1")) {
        *value = true;
    } else if (StringCmpIgnoreCase(strValue, "false") || StringCmpIgnoreCase(strValue, "0")) {
        *value = false;
    }

    return err;
}

/* 获取section段第一个键为key的string值,成功返回获取的值,否则返回默认值 */
void IniFile::GetStringValueOrDefault(const string &section, const string &key,
                                      string *value, const string &defaultValue)
{
    if (GetStringValue(section, key, value) != 0) {
        *value = defaultValue;
    }

    return;
}

/* 获取section段第一个键为key的int值,成功返回获取的值,否则返回默认值 */
void IniFile::GetIntValueOrDefault(const string &section, const string &key, int *value, int defaultValue)
{
    if (GetIntValue(section, key, value) != 0) {
        *value = defaultValue;
    }

    return;
}

/* 获取section段第一个键为key的double值,成功返回获取的值,否则返回默认值 */
void IniFile::GetDoubleValueOrDefault(const string &section, const string &key, double *value, double defaultValue)
{
    if (GetDoubleValue(section, key, value) != 0) {
        *value = defaultValue;
    }

    return;
}

/* 获取section段第一个键为key的bool值,成功返回获取的值,否则返回默认值 */
void IniFile::GetBoolValueOrDefault(const string &section, const string &key, bool *value, bool defaultValue)
{
    if (GetBoolValue(section, key, value) != 0) {
        *value = defaultValue;
    }

    return;
}

/* 获取注释,如果key=""则获取段注释 */
int IniFile::GetComment(const string &section, const string &key, string *comment)
{
    IniSection *sect = getSection(section);

    if (sect == NULL) {
        errMsg = string("not find the section ")+section;
        return ERR_NOT_FOUND_SECTION;
    }

    if (key == "") {
        *comment = sect->comment;
        return RET_OK;
    }

    for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
        if (it->key == key) {
            *comment = it->comment;
            return RET_OK;
        }
    }

    errMsg = string("not find the key ")+section;
    return ERR_NOT_FOUND_KEY;
}

/* 获取行尾注释,如果key=""则获取段的行尾注释 */
int IniFile::GetRightComment(const string &section, const string &key, string *rightComment)
{
    IniSection *sect = getSection(section);

    if (sect == NULL) {
        errMsg = string("not find the section ")+section;
        return ERR_NOT_FOUND_SECTION;
    }

    if (key == "") {
        *rightComment = sect->rightComment;
        return RET_OK;
    }

    for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
        if (it->key == key) {
            *rightComment = it->rightComment;
            return RET_OK;
        }
    }

    errMsg = string("not find the key ")+key;
    return ERR_NOT_FOUND_KEY;
}

int IniFile::getValue(const string &section, const string &key, string *value)
{
    string comment;
    return getValue(section, key, value, &comment);
}

int IniFile::getValue(const string &section, const string &key, string *value, string *comment)
{
    IniSection *sect = getSection(section);

    if (sect == NULL) {
        errMsg = string("not find the section ")+section;
        return ERR_NOT_FOUND_SECTION;
    }

    for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
        if (it->key == key) {
            *value = it->value;
            *comment = it->comment;
            return RET_OK;
        }
    }

    errMsg = string("not find the key ")+key;
    return ERR_NOT_FOUND_KEY;
}

int IniFile::GetValues(const string &section, const string &key, vector<string> *values)
{
    vector<string> comments;
    return GetValues(section, key, values, &comments);
}

int IniFile::GetValues(const string &section, const string &key, vector<string> *values, vector<string> *comments)
{
    string value, comment;

    values->clear();
    comments->clear();

    IniSection *sect = getSection(section);

    if (sect == NULL) {
        errMsg = string("not find the section ")+section;
        return ERR_NOT_FOUND_SECTION;
    }

    for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
        if (it->key == key) {
            value = it->value;
            comment = it->comment;

            values->push_back(value);
            comments->push_back(comment);
        }
    }

    if (values->size() == 0) {
        errMsg = string("not find the key ")+key;
        return ERR_NOT_FOUND_KEY;
    }

    return RET_OK;
}

bool IniFile::HasSection(const string &section)
{
    return (getSection(section) != NULL);
}

bool IniFile::HasKey(const string &section, const string &key)
{
    IniSection *sect = getSection(section);

    if (sect != NULL) {
        for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
            if (it->key == key) {
                return true;
            }
        }
    }

    return false;
}

int IniFile::setValue(const string &section, const string &key, const string &value, const string &comment /*=""*/)
{
    IniSection *sect = getSection(section);

    string comt = comment;

    if (comt != "") {
        comt = commentDelimiter + comt;
    }

    if (sect == NULL) {
        //如果段不存在,新建一个
        sect = new IniSection();

        if (sect == NULL) {
            errMsg = string("no enough memory!");
            return ERR_NO_ENOUGH_MEMORY;
        }

        sect->name = section;
        if (sect->name == "") {
            // 确保空section在第一个
            sections_vt.insert(sections_vt.begin(), sect);
        } else {
            sections_vt.push_back(sect);
        }
    }

    for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
        if (it->key == key) {
            it->value = value;
            it->comment = comt;
            return RET_OK;
        }
    }

    // not found key
    IniItem item;
    item.key = key;
    item.value = value;
    item.comment = comt;

    sect->items.push_back(item);

    return RET_OK;
}

int IniFile::SetStringValue(const string &section, const string &key, const string &value)
{
    return setValue(section, key, value);
}

int IniFile::SetIntValue(const string &section, const string &key, int value)
{
    char buf[64] = {0};
    snprintf(buf, sizeof(buf), "%d", value);
    return setValue(section, key, buf);
}

int IniFile::SetDoubleValue(const string &section, const string &key, double value)
{
    char buf[64] = {0};
    snprintf(buf, sizeof(buf), "%f", value);
    return setValue(section, key, buf);
}

int IniFile::SetBoolValue(const string &section, const string &key, bool value)
{
    if (value) {
        return setValue(section, key, "true");
    } else {
        return setValue(section, key, "false");
    }
}

int IniFile::SetComment(const string &section, const string &key, const string &comment)
{
    IniSection *sect = getSection(section);

    if (sect == NULL) {
        errMsg = string("Not find the section ")+section;
        return ERR_NOT_FOUND_SECTION;
    }

    if (key == "") {
        sect->comment = comment;
        return RET_OK;
    }

    for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
        if (it->key == key) {
            it->comment = comment;
            return RET_OK;
        }
    }

    errMsg = string("not find the key ")+key;
    return ERR_NOT_FOUND_KEY;
}

int IniFile::SetRightComment(const string &section, const string &key, const string &rightComment)
{
    IniSection *sect = getSection(section);

    if (sect == NULL) {
        errMsg = string("Not find the section ")+section;
        return ERR_NOT_FOUND_SECTION;
    }

    if (key == "") {
        sect->rightComment = rightComment;
        return RET_OK;
    }

    for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
        if (it->key == key) {
            it->rightComment = rightComment;
            return RET_OK;
        }
    }

    errMsg = string("not find the key ")+key;
    return ERR_NOT_FOUND_KEY;
}

void IniFile::SetCommentDelimiter(const string &delimiter)
{
    commentDelimiter = delimiter;
}

void IniFile::DeleteSection(const string &section)
{
    for (IniSection_it it = sections_vt.begin(); it != sections_vt.end(); ) {
        if ((*it)->name == section) {
            delete *it;
            it = sections_vt.erase(it);
            break;
        } else {
            it++;
        }
    }
}

void IniFile::DeleteKey(const string &section, const string &key)
{
    IniSection *sect = getSection(section);

    if (sect != NULL) {
        for (IniSection::IniItem_it it = sect->begin(); it != sect->end();) {
            if (it->key == key) {
                it = sect->items.erase(it);
                break;
            } else {
                it++;
            }
        }
    }
}

/*-------------------------------------------------------------------------*/
/**
  @brief    release: 释放全部资源,清空容器
  @param    none
  @return   none
 */
/*--------------------------------------------------------------------------*/
void IniFile::release()
{
    iniFilePath = "";

    for (IniSection_it it = sections_vt.begin(); it != sections_vt.end(); ++it) {
        delete (*it);  // 清除section
    }

    sections_vt.clear();
}

/*-------------------------------------------------------------------------*/
/**
  @brief    判断是否是注释
  @param    str 一个string变量
  @return   如果是注释则为真
 */
/*--------------------------------------------------------------------------*/
bool IniFile::IsCommentLine(const string &str)
{
    return StartWith(str, commentDelimiter);
}

/*-------------------------------------------------------------------------*/
/**
  @brief    print for debug
  @param    none
  @return   none
 */
/*--------------------------------------------------------------------------*/
void IniFile::print()
{
    printf("############ print start ############\n");
    printf("filePath:[%s]\n", iniFilePath.c_str());
    printf("commentDelimiter:[%s]\n", commentDelimiter.c_str());

    for (IniSection_it it = sections_vt.begin(); it != sections_vt.end(); ++it) {
        printf("comment :[\n%s]\n", (*it)->comment.c_str());
        printf("section :\n[%s]\n", (*it)->name.c_str());
        if ((*it)->rightComment != "") {
            printf("rightComment:\n%s", (*it)->rightComment.c_str());
        }

        for (IniSection::IniItem_it i = (*it)->items.begin(); i != (*it)->items.end(); ++i) {
            printf("    comment :[\n%s]\n", i->comment.c_str());
            printf("    parm    :%s=%s\n", i->key.c_str(), i->value.c_str());
            if (i->rightComment != "") {
                printf("    rcomment:[\n%s]\n", i->rightComment.c_str());
            }
        }
    }

    printf("############ print end ############\n");
    return;
}

const string & IniFile::GetErrMsg()
{
    return errMsg;
}

bool IniFile::StartWith(const string &str, const string &prefix)
{
    if (strncmp(str.c_str(), prefix.c_str(), prefix.size()) == 0) {
        return true;
    }

    return false;
}

void IniFile::trimleft(string &str, char c /*=' '*/)
{
    int len = str.length();

    int i = 0;

    while (str[i] == c && str[i] != '\0') {
        i++;
    }

    if (i != 0) {
        str = string(str, i, len - i);
    }
}

void IniFile::trimright(string &str, char c /*=' '*/)
{
    int i = 0;
    int len = str.length();

    for (i = len - 1; i >= 0; --i) {
        if (str[i] != c) {
            break;
        }
    }

    str = string(str, 0, i + 1);
}

/*-------------------------------------------------------------------------*/
/**
  @brief    trim,整理一行字符串,去掉首尾空格
  @param    str string变量
 */
/*--------------------------------------------------------------------------*/
void IniFile::trim(string &str)
{
    int len = str.length();

    int i = 0;

    while ((i < len) && isspace(str[i]) && (str[i] != '\0')) {
        i++;
    }

    if (i != 0) {
        str = string(str, i, len - i);
    }

    len = str.length();

    for (i = len - 1; i >= 0; --i) {
        if (!isspace(str[i])) {
            break;
        }
    }

    str = string(str, 0, i + 1);
}

/*-------------------------------------------------------------------------*/
/**
  @brief    split,用分隔符切割字符串
  @param    str 输入字符串
  @param    left_str 分隔后得到的左字符串
  @param    right_str 分隔后得到的右字符串(不包含seperator)
  @param    seperator 分隔符
  @return   pos
 */
/*--------------------------------------------------------------------------*/
bool IniFile::split(const string &str, const string &sep, string *pleft, string *pright)
{
    size_t pos = str.find(sep);
    string left, right;

    if (pos != string::npos) {
        left = string(str, 0, pos);
        right = string(str, pos+1);

        trim(left);
        trim(right);

        *pleft = left;
        *pright = right;
        return true;
    } else {
        left = str;
        right = "";

        trim(left);

        *pleft = left;
        *pright = right;
        return false;
    }
}


bool IniFile::StringCmpIgnoreCase(const string &str1, const string &str2)
{
    string a = str1;
    string b = str2;
    transform(a.begin(), a.end(), a.begin(), towupper);
    transform(b.begin(), b.end(), b.begin(), towupper);

    return (a == b);
}



}  /* namespace inifile */

makefile

ifeq ($(DEBUG),Enable)
	CPPFLAGS = -D_DEBUG -g -Wall 
else
	CPPFLAGS = -s 
endif 

INCS=-I./
LIBS=./lib
OUTDIR=./
TARGET=ini_test

exe:
	g++  -std=gnu++11  $(CPPFLAGS) $(INCS) ./*.cpp   -o $(OUTDIR)/$(TARGET)

all: exe

clean:
	rm 	$(OUTDIR)/$(TARGET)


  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: INIInitial Input)配置文件是一种常用的配置文件格式,用于存储和读取程序的配置信息。以下是读写INI配置文件的步骤: 1. 读取INI配置文件:首先,我们需要打开INI配置文件,并逐行读取文件内容。可以使用适当的函数或库来实现文件读取操作。在读取过程中,我们需要解析每一行内容,并提取所需的配置信息。 2. 解析INI配置文件:在解析每一行配置信息之前,我们还需要进行一些校验和处理。首先,我们需要忽略注释行(行首以分号 “;” 或井号 “#” 开头的行),然后我们需要忽略空行。接下来,我们可以使用适当的函数或算法解析每一行的配置信息。一般来说,每一行配置信息的格式为“键=值”的形式,我们需要提取出键和对应的值。 3. 存储INI配置文件:如果需要修改INI配置文件或添加新的配置项,我们需要打开INI配置文件,并写入新的配置信息。首先,我们需要读取原有的配置信息,并将其保存到内存中。然后,我们可以使用合适的函数或库来修改配置信息或添加新的配置项。最后,我们将修改后的配置信息写入INI配置文件。 4. 错误处理:在读写INI配置文件的过程中,如果遇到错误,例如文件不存在、文件权限不足、文件格式错误等,我们需要进行适当的错误处理。可以根据实际情况输出错误信息或进行其他操作。 总结:读写INI配置文件是一种常见的配置文件操作方法,需要按照一定的步骤进行。通过逐行读取解析配置文件内容,可以实现读取INI配置文件的功能。通过修改和添加配置信息,并将其写入配置文件,可以实现存储INI配置文件的功能。在进行读写操作时,还需要注意错误处理,以保证程序的稳定性和可靠性。 ### 回答2: INI配置文件是一种常见的配置文件格式,用于存储程序的配置信息。C语言提供了一些函数库用于读写INI文件,包括<Windows.h>头文件中的GetPrivateProfileString、GetPrivateProfileInt、WritePrivateProfileString等函数。 首先,要读取INI配置文件中的值,可以使用GetPrivateProfileString函数。该函数的参数包括INI文件的路径、节名和键名,同时可以传入一个缓冲区,函数将根据配置文件中的键值将对应的值复制到缓冲区中。 另外,如果配置文件中的值是整数类型的,可以使用GetPrivateProfileInt函数,该函数会直接返回键值对应的整数值。 如果需要写入INI配置文件,可以使用WritePrivateProfileString函数。该函数的参数包括INI文件的路径、节名、键名和值。调用该函数后,程序会将键值对按照指定的格式写入配置文件中。 在使用这些函数前,需要先加载Windows.h头文件。同时,在使用INI配置文件时,需要注意配置文件的路径是否正确,以及节名和键名是否正确。读取INI文件时,还要判断读取的值是否为空,以避免出现错误。 总结起来,C语言提供了一些函数用于读写INI配置文件,这些函数可以方便地读取和写入配置信息。通过合理的使用这些函数,可以更好地管理程序的配置,提升程序的可配置性和可维护性。 ### 回答3: INIInitialization)是一种常见的配置文件格式,用于存储应用程序的设置和参数。在C语言中,可以通过读写INI配置文件来实现配置文件的加载和保存。 在读取INI配置文件时,可以使用标准库函数fopen()来打开文件,然后通过fgets()函数逐行读取文件内容。读取到的每一行都可以通过字符串处理函数来分割成键值对。常用的字符串处理函数包括strtok()、strstr()和sscanf()等。使用时需要根据INI配置文件的具体格式和规范来进行相应的处理。 在写入INI配置文件时,可以使用标准库函数fopen()来创建或打开文件,然后使用fprintf()函数来向文件写入内容。需要注意的是,写入INI配置文件时需要按照一定的格式和规范来进行写入,以保证配置文件的正确性和可读性。 读写INI配置文件的步骤主要包括以下几个方面: 1. 打开INI配置文件:使用fopen()函数打开INI配置文件。 2. 读取INI配置文件内容:使用fgets()函数逐行读取配置文件内容,并使用字符串处理函数处理每一行的内容。 3. 解析INI配置文件内容:根据INI配置文件的格式和规范,将每一行的内容解析成键值对,并存储到相应的数据结构中。 4. 关闭INI配置文件:使用fclose()函数关闭INI配置文件,释放资源。 5. 根据需要进行数据操作:根据存储的键值对,进行相应的数据操作,如设置应用程序的参数、初始化等。 6. 写入INI配置文件:使用fprintf()函数向INI配置文件写入数据,按照INI配置文件的格式和规范进行写入。 总结:通过使用C语言提供的标准库函数,可以实现INI配置文件读取和写入。读取时需要逐行读取解析每一行的内容,写入时需要按照INI配置文件的格式进行写入。读写INI配置文件是一种常见的配置文件处理方式,具有简单、灵活的优点,适用于各种应用程序的配置管理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值