源自发布跨平台INI文件读写API(C++版本) V0.2.1
使用说明请参考该链接。
下面的版本对源码做了改进:
1. 修改了等号两边不能有空格或~t的问题
2. 增加了readBool方法
/** * @file iniFile.h * @brief initialization file read and write API * @author Deng Yangjun * @date 2007-12-9 * @version 0.2.1 * <pre><b>email: </b></pre> * (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. * <pre>Don Hao修改了等号两边不能有空格或~t的问题</b></pre> * <pre>Don Hao增加了readBool方法</b></pre> */ #ifndef _INIFILECPP_H #define _INIFILECPP_H #include <string> class IniFile { public: IniFile(const std::string & fileName); public: virtual ~IniFile(void); const std::string &getFileName() const; const std::string &getSection() const; void setSection(const std::string §ion); bool write(const std::string &key, const std::string & value) const ; bool write(const std::string &key, int value) const ; std::string readStr(const std::string &key, const std::string &default_value) const; int readInt(const std::string &key, int default_value) const; bool readBool(const std::string &key, bool 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 bool read_profile_bool(const char *section, const char *key, bool 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: std::string m_fileName; std::string m_section; }; #endif
/** * @file iniFile.cpp * @brief initialization file read and write API implementation * @author Deng Yangjun * @date 2008 - 11 - 13 * @version 0.2.1 * <pre><b>email: </b></pre> * (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. * <pre><b>Moficication: </b></pre> * <pre>Don Hao修改了等号两边不能有空格或~t的问题</b></pre> * <pre>Don Hao增加了readBool方法</b></pre> */ #include "IniFile.h" #include <fstream> #include <cassert> #include <cstdio> #include <cstdlib> const int MAX_INI_FILE_SIZE = 1024 * 16; IniFile::IniFile(const std::string & fileName) { m_fileName = fileName; } IniFile::~IniFile(void) { } const std::string & IniFile::getFileName() const { return m_fileName; } void IniFile::setSection(const std::string §ion) { m_section = section; } bool IniFile::write(const std::string &key, const std::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 std::string &key, int value) const { char tmp[64]; _snprintf(tmp, strlen(tmp) - 1, "%d", value); return write(key, tmp); } std::string IniFile::readStr(const std::string &key, const std::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 std::string &key, int default_value) const { return read_profile_int(m_section.c_str(), key.c_str(), default_value, m_fileName.c_str()); } bool IniFile::readBool(const std::string &key, bool default_value) const { return read_profile_bool(m_section.c_str(), key.c_str(), default_value, m_fileName.c_str()); } const std::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 (i - section_start == strlen(section) && 0 == strncmp(p + section_start, section, strlen(section))) { 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; int valid = j; if ('#' != p[j]) // skip over comment { while (j < i && p[j] != '=') { ++j; if (' ' != p[j] && '/t' != p[j] && '=' != p[j]) valid = j; if ('=' == p[j]) { if (j - newline_start == strlen(key) && strncmp(key, p + newline_start, strlen(key)) == 0) { // find the key ok *key_s = newline_start; *key_e = j - 1; valid = j + 1; while (' ' == p[valid] || '/t' == p[valid]) valid++; *value_s = valid; *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); } } bool IniFile::read_profile_bool(const char *section, const char *key, bool default_value, const char *file) { char value[32] = {0}; if (!read_profile_string(section, key, value, sizeof(value), NULL, file)) { return default_value; } else { for(int i = 0; i < sizeof(value); ++i) value[i]=tolower(value[i]); std::string boolValue = static_cast<std::string>(value); if ("true" == boolValue) { return true; } else { return false; } } } /** * @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; }