`
dqifa
  • 浏览: 112111 次
社区版块
存档分类
最新评论

C++读写ini的类

阅读更多
        =====文件名:IniFile.h=====
/**
* @file
* @brief initialization file read and write API
* @author Deng Yangjun
* @date 2007-12-9
* @version 0.2
*  (C)2007 Midapex
* This program is free software; you can redistribute it and/or modify it
*  under the terms of the GNU Library General Public License as published
*  by the Free Software Foundation; either version 2 of the License,
*  or (at your option) any later version.
*/
#ifndef INI_FILE_CPP_H_
#define INI_FILE_CPP_H_

#include <string>
using namespace std;

class IniFile
{
public:
    IniFile(const string & fileName);
public:
    virtual ~IniFile(void);

    const string & getFileName() const;

    const string &getSection() const;
    void setSection(const string §ion);

    bool write(const string &key, const string & value) const ;
    bool write(const string &key, int value) const ;

    string readStr(const string &key,const string &default_value) const;
    int readInt(const string &key, int default_value) const;

public:
    static int read_profile_string( const char *section, const char *key,char *value,
        int size, const char *default_value, const char *file);
    static int read_profile_int( const char *section, const char *key,int default_value,
        const char *file);
    static int write_profile_string(const char *section, const char *key,
        const char *value, const char *file);

private:
    static int load_ini_file(const char *file, char *buf,int *file_size);
    static int newline(char c);
    static int end_of_string(char c);
    static int left_barce(char c);
    static int right_brace(char c );
    static int parse_file(const char *section, const char *key, const char *buf,int *sec_s,int *sec_e,
        int *key_s,int *key_e, int *value_s, int *value_e);

private:
    string m_fileName;
    string m_section;
};

#endif

        =====文件名:IniFile.cpp=====
/*
 * @file
 * @brief initialization file read and write API implementation
 * @author Deng Yangjun
 * @date 2007-12-9
 * @version 0.2
 * (C)2007 Midapex
 * This program is free software; you can redistribute it and/or modify it
*  under the terms of the GNU Library General Public License as published
*  by the Free Software Foundation; either version 2 of the License,
*  or (at your option) any later version.
 */
#include "IniFile.h"
#include <fstream>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#define MAX_INI_FILE_SIZE 1024*16

IniFile::IniFile(const string & fileName)
{
    m_fileName = fileName;
}

IniFile::~IniFile(void)
{
}

const string & IniFile::getFileName() const
{
    return m_fileName;
}

void IniFile::setSection(const string §ion)
{
    m_section = section;
}

bool IniFile::write(const string &key, const string & value) const
{
    return write_profile_string(m_section.c_str(),key.c_str(),value.c_str(),m_fileName.c_str())==1? true:false;
}

bool IniFile::write(const string &key, int value) const
{
    char tmp[64];
    sprintf(tmp,"%d",value);
    return write(key,tmp);
}

string IniFile::readStr(const string &key,const string &default_value) const
{
    char buf[4096];
    read_profile_string(m_section.c_str(),key.c_str(),buf,sizeof(buf),default_value.c_str(),m_fileName.c_str());
    return buf;
}

int IniFile::readInt(const string &key, int default_value) const
{
    return read_profile_int(m_section.c_str(),key.c_str(),default_value,m_fileName.c_str());
}

const string &IniFile::getSection() const
{
    return m_section;
}

int IniFile::load_ini_file(const char *file, char *buf,int *file_size)
{
    FILE *in = NULL;
    int i=0;
    *file_size =0;

    assert(file !=NULL);
    assert(buf !=NULL);

    in = fopen(file,"r");
    if( NULL == in) {
        return 0;
    }

    buf[i]=fgetc(in);

    //load initialization file
    while( buf[i]!= (char)EOF) {
        i++;
        assert( i < MAX_INI_FILE_SIZE ); //file too big, you can redefine MAX_INI_FILE_SIZE to fit the big file
        buf[i]=fgetc(in);
    }

    buf[i]='\0';
    *file_size = i;

    fclose(in);
    return 1;
}

int IniFile::newline(char c)
{
    return ('\n' == c ||  '\r' == c )? 1 : 0;
}
int IniFile::end_of_string(char c)
{
    return '\0'==c? 1 : 0;
}
int IniFile::left_barce(char c)
{
    return '[' == c? 1 : 0;
}
int IniFile::right_brace(char c )
{
    return ']' == c? 1 : 0;
}
int IniFile::parse_file(const char *section, const char *key, const char *buf,int *sec_s,int *sec_e,
                      int *key_s,int *key_e, int *value_s, int *value_e)
{
    const char *p = buf;
    int i=0;

    assert(buf!=NULL);
    assert(section != NULL && strlen(section));
    assert(key != NULL && strlen(key));

    *sec_e = *sec_s = *key_e = *key_s = *value_s = *value_e = -1;

    while( !end_of_string(p[i]) ) {
        //find the section
        if( ( 0==i ||  newline(p[i-1]) ) && left_barce(p[i]) )
        {
            int section_start=i+1;

            //find the ']'
            do {
                i++;
            } while( !right_brace(p[i]) && !end_of_string(p[i]));

            if( 0 == strncmp(p+section_start,section, i-section_start)) {
                int newline_start=0;

                i++;

                //Skip over space char after ']'
                while(isspace(p[i])) {
                    i++;
                }

                //find the section
                *sec_s = section_start;
                *sec_e = i;

                while( ! (newline(p[i-1]) && left_barce(p[i]))
                    && !end_of_string(p[i]) ) {
                        int j=0;
                        //get a new line
                        newline_start = i;

                        while( !newline(p[i]) &&  !end_of_string(p[i]) ) {
                            i++;
                        }

                        //now i  is equal to end of the line
                        j = newline_start;

                        if(';' != p[j]) //skip over comment
                        {
                            while(j < i && p[j]!='=') {
                                j++;
                                if('=' == p[j]) {
                                    if(strncmp(key,p+newline_start,j-newline_start)==0)
                                    {
                                        //find the key ok
                                        *key_s = newline_start;
                                        *key_e = j-1;

                                        *value_s = j+1;
                                        *value_e = i;

                                        return 1;
                                    }
                                }
                            }
                        }

                        i++;
                }
            }
        }
        else
        {
            i++;
        }
    }
    return 0;
}

/*
*@brief read string in initialization file\n
* retrieves a string from the specified section in an initialization file
*@param section [in] name of the section containing the key name
*@param key [in] name of the key pairs to value
*@param value [in] pointer to the buffer that receives the retrieved string
*@param size [in] size of result's buffer
*@param default_value [in] default value of result
*@param file [in] path of the initialization file
*@return 1 : read success; \n 0 : read fail
*/
int IniFile::read_profile_string( const char *section, const char *key,char *value,
                        int size, const char *default_value, const char *file)
{
    char buf[MAX_INI_FILE_SIZE]={0};
    int file_size;
    int sec_s,sec_e,key_s,key_e, value_s, value_e;

    //check parameters
    assert(section != NULL && strlen(section));
    assert(key != NULL && strlen(key));
    assert(value != NULL);
    assert(size > 0);
    assert(file !=NULL &&strlen(key));

    if(!load_ini_file(file,buf,&file_size))
    {
        if(default_value!=NULL)
        {
            strncpy(value,default_value, size);
        }
        return 0;
    }

    if(!parse_file(section,key,buf,&sec_s,&sec_e,&key_s,&key_e,&value_s,&value_e))
    {
        if(default_value!=NULL)
        {
            strncpy(value,default_value, size);
        }
        return 0; //not find the key
    }
    else
    {
        int cpcount = value_e -value_s;

        if( size-1 < cpcount)
        {
            cpcount =  size-1;
        }

        memset(value, 0, size);
        memcpy(value,buf+value_s, cpcount );
        value[cpcount] = '\0';

        return 1;
    }
}

/*
*@brief read int value in initialization file\n
* retrieves int value from the specified section in an initialization file
*@param section [in] name of the section containing the key name
*@param key [in] name of the key pairs to value
*@param default_value [in] default value of result
*@param file [in] path of the initialization file
*@return profile int value,if read fail, return default value
*/
int IniFile::read_profile_int( const char *section, const char *key,int default_value,
                     const char *file)
{
    char value[32] = {0};
    if(!read_profile_string(section,key,value, sizeof(value),NULL,file))
    {
        return default_value;
    }
    else
    {
        return atoi(value);
    }
}

/*
* @brief write a profile string to a ini file
* @param section [in] name of the section,can't be NULL and empty string
* @param key [in] name of the key pairs to value, can't be NULL and empty string
* @param value [in] profile string value
* @param file [in] path of ini file
* @return 1 : success\n 0 : failure
*/
int IniFile::write_profile_string(const char *section, const char *key,
                         const char *value, const char *file)
{
    char buf[MAX_INI_FILE_SIZE]={0};
    char w_buf[MAX_INI_FILE_SIZE]={0};
    int sec_s,sec_e,key_s,key_e, value_s, value_e;
    int value_len = (int)strlen(value);
    int file_size;
    FILE *out;

    //check parameters
    assert(section != NULL && strlen(section));
    assert(key != NULL && strlen(key));
    assert(value != NULL);
    assert(file !=NULL &&strlen(key));

    if(!load_ini_file(file,buf,&file_size))
    {
        sec_s = -1;
    }
    else
    {
        parse_file(section,key,buf,&sec_s,&sec_e,&key_s,&key_e,&value_s,&value_e);
    }

    if( -1 == sec_s)
    {
        if(0==file_size)
        {
            sprintf(w_buf+file_size,"[%s]\n%s=%s\n",section,key,value);
        }
        else
        {
            //not find the section, then add the new section at end of the file
            memcpy(w_buf,buf,file_size);
            sprintf(w_buf+file_size,"\n[%s]\n%s=%s\n",section,key,value);
        }
    }
    else if(-1 == key_s)
    {
        //not find the key, then add the new key=value at end of the section
        memcpy(w_buf,buf,sec_e);
        sprintf(w_buf+sec_e,"%s=%s\n",key,value);
        sprintf(w_buf+sec_e+strlen(key)+strlen(value)+2,buf+sec_e, file_size - sec_e);
    }
    else
    {
        //update value with new value
        memcpy(w_buf,buf,value_s);
        memcpy(w_buf+value_s,value, value_len);
        memcpy(w_buf+value_s+value_len, buf+value_e, file_size - value_e);
    }

    out = fopen(file,"w");
    if(NULL == out)
    {
        return 0;
    }

    if(-1 == fputs(w_buf,out) )
    {
        fclose(out);
        return 0;
    }

    fclose(out);
    return 1;
}

        =====文件名:IniFileCpp.cpp=====
#include "IniFile.h"
#include <iostream>
using namespace std;

int main()
{
    cout << "Midapex IniFile API 0.2.0" << endl;
    string name_key = "name";
    string age_key = "age";

    IniFile ini("myconfig.ini");
    ini.setSection("student");
//    if(!ini.write(name_key,"Tony"))
//    {
//        cout << "write name to ini file fail"<<endl;
//        return -1;
//    }
    if(!ini.write(age_key,20))
    {
        cout << "write age to ini file fail"<<endl;
        return -1;
    }

    cout << "[" << ini.getSection()<< "]" <<endl;
    cout << name_key << "=" << ini.readStr(name_key,"") << endl;
    cout << age_key << "=" << ini.readInt(age_key,-1) << endl;

    ini.setSection("teacher");
    if(!ini.write(name_key,"Tom"))
    {
        cout << "write name to ini file fail"<<endl;
        return -1;
    }
    if(!ini.write(age_key,50))
    {
        cout << "write age to ini file fail"<<endl;
        return -1;
    }

    cout << "[" << ini.getSection()<< "]" <<endl;
    cout << name_key << "=" << ini.readStr(name_key,"") << endl;
    cout << age_key << "=" << ini.readInt(age_key,-1) << endl;

    return 0;
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics