CConfig.h

#ifndef _CCONFIG_H
#define _CCONFIG_H
#include <iostream>
#include <string>
#include <fstream>
#include <vector> using namespace std; class CConfig
{
public:
CConfig();
~CConfig();
void SetFilePath(const string &filePath);
string GetFilePath();
bool GetValue(const string &section, const string &key, string &value, string &error);
bool ModifyValue(const string &section, const string &key, const string &value, string &error); private:
bool OpenFile();
bool FindSection(const string &sectionName);
bool FindKey(const string &key);
bool OpenFileRead();
bool OpenFileWrite();
bool SetValue(const string &key, const string &value);
void WriteFile(vector<string> &vContent); string m_filePath;
fstream m_fout;
fstream m_fin;
string m_content;
string m_value;
string m_error;
};
#endif

CConfig.cpp

/********************************************************
Copyright (C), 2016-2018,
FileName: CConfig
Author: woniu201
Created: 2018/11/16
Description: 纯C++实现配置文件的操作
********************************************************/
#include "CConfig.h" CConfig::CConfig()
{ } CConfig::~CConfig()
{ } /************************************
@ Brief: 设置配置文件路径
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
void CConfig::SetFilePath(const string &filePath)
{
m_filePath = filePath;
} /************************************
@ Brief: 读取配置文件路径
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
string CConfig::GetFilePath()
{
return this->m_filePath;
} /************************************
@ Brief: 打开配置文件
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
bool CConfig::OpenFile()
{
if (true == m_fin.is_open())
{
m_fin.close();
} m_fin.open(m_filePath.c_str()); if (!m_fin.is_open())
{
m_error = "open file fail:" + m_filePath;
return false;
}
return true;
} /************************************
@ Brief: 找节名
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
bool CConfig::FindSection(const string &sectionName)
{
if (-1 != m_content.find('['))
{
string sTemp = m_content.substr(m_content.find('[') + 1, m_content.find(']') - m_content.find('[') - 1);
if (0 == strcmp(sTemp.c_str(), sectionName.c_str()))
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
} /************************************
@ Brief: 找键名
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
bool CConfig::FindKey(const string &key)
{
size_t iDelePlace = m_content.find((char)'//', 0);
size_t iFindEqual = m_content.find((char)'=', 0);
//被注释的行,或者是包含key但是已经被注视掉了,过滤
if ((-1 != iDelePlace && iDelePlace < iFindEqual) || (-1 != iDelePlace && -1 == iFindEqual) || -1 == iFindEqual)
{
return false;
}
string sKey = m_content.substr(0, m_content.find('=')); if (0 == strcmp(sKey.c_str(), key.c_str()))
{
m_value = m_content.substr(m_content.find('=') + 1, m_content.length() - m_content.find('=') - 1);
return true;
}
return false;
} /************************************
@ Brief: 读取节下Key对应的value值
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
bool CConfig::GetValue(const string &section, const string &key, string &value, string &error)
{
m_error = "";
if (false == OpenFile())
{
error = m_error;
return false;
}
char str[4096] = { 0 };
bool bFindSection = false;
while (m_fin.getline(str, sizeof(str)))
{
m_content = str;
if (!bFindSection)
{
if (FindSection(section))
{
bFindSection = true;
}
else
{
m_error = "";
m_error = "节点" + section + "不存在";
}
}
else
{
if (FindKey(key))
{
m_fin.close();
m_error = "";
value = m_value;
return true;
}
else
{
m_error = "";
m_error = "键名" + key + "不存在";
}
}
memset(str, 0, 4096);
}
error = m_error;
m_fin.close();
return false;
} /************************************
@ Brief: 读的方式打开文件
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
bool CConfig::OpenFileRead()
{
m_fout.close();
//关闭后要在清空一下,否则下次打开会出错
m_fout.clear();
m_fout.open(m_filePath.c_str(), ios::in);
if (!m_fout.is_open())
{
m_error = "open file fail:" + m_filePath;
return false;
}
return true;
} /************************************
@ Brief: 写的方式打开文件
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
bool CConfig::OpenFileWrite()
{
m_fout.close();
//关闭后要在清空一下,否则下次打开会出错
m_fout.clear();
m_fout.open(m_filePath.c_str(), ios::out | ios::trunc);
if (!m_fout.is_open())
{
m_error = "can not open file " + m_filePath;
return false;
}
return true;
} /************************************
@ Brief: 找KEY,设置新值
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
bool CConfig::SetValue(const string &key, const string &value)
{
size_t iDelePlace = m_content.find((char)'//');
size_t iFindEqual = m_content.find((char)'=');
//被注释的行,或者是包含key但是已经被注视掉了,过滤
if ((-1 != iDelePlace && iDelePlace < iFindEqual) || (-1 != iDelePlace && -1 == iFindEqual) || -1 == iFindEqual)
{
return false;
}
string sKey = m_content.substr(0, m_content.find('=')); if (0 == strcmp(sKey.c_str(), key.c_str()))
{
m_content = m_content.substr(0, m_content.find('=') + 1) + value;
return true;
} return false;
} /************************************
@ Brief: 修改配置文件KEY对应的value
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
bool CConfig::ModifyValue(const string &section, const string &key, const string &value, string &error)
{
m_error = "";
if (false == OpenFileRead())
{
error = m_error;
return false;
} char str[4096] = { 0 };
vector<string> vContent;
bool isModify = false;
bool isFindSection = false;
while ( (m_fout.getline(str, sizeof(str))))
{
m_content = str;
if (!isFindSection)
{
if (FindSection(section))
{
isFindSection = true;
}
else
{
m_error = "";
m_error = "节点" + section + "不存在";
}
}
else
{
if (!isModify)
{
if (SetValue(key, value))
{
isModify = true;
}
else
{
m_error = "";
m_error = "键名" + key + "不存在";
}
}
}
vContent.push_back(m_content);
m_content = "";
memset(str, 0, 4096);
}
error = m_error;
WriteFile(vContent);
m_fout.flush();
m_fout.close();
return isModify;
} /************************************
@ Brief: 写文件
@ Author: woniu201
@ Created: 2018/12/21
@ Return:
************************************/
void CConfig::WriteFile(vector<string> &vContent)
{
if (false == OpenFileWrite())
{
m_fout.close();
return;
}
for (size_t iIndex = 0; iIndex < vContent.size(); iIndex++)
{
m_fout << vContent[iIndex] << endl;
}
m_fout.close();
vector<string>().swap(vContent);
}

main.cpp

#include "CConfig.h"

int main()
{
CConfig config;
config.SetFilePath("a.ini");
string value = "";
string error = "";
config.GetValue("ServerUrl", "PcName", value, error); cout << value << endl;
cout << error << endl; error = "";
config.ModifyValue("ServerUrl", "PcName", "5.0", error);
cout << error << endl; getchar();
}

配置文件a.ini内容如下:

纯C++实现操作配置文件(告别跨平台问题)的更多相关文章

  1. 操作配置文件Properties

    // */ // ]]>   操作配置文件Properties Table of Contents 1 定义 2 读取配置值 3 修改和保存配置 4 注意 1 定义 csharp中在Settin ...

  2. day20 二十、加密模块、操作配置文件、操作shell命令、xml模块

    一.加密模块 1.hashlib模块:加密 ①有解密的加密方式 ②无解密的加密方式:碰撞检查 -- 1)不同数据加密后的结果一定不一致 -- 2)相同数据的加密结果一定是一致的 import hash ...

  3. 支持断线重连、永久watcher、递归操作并且能跨平台(.NET Core)的ZooKeeper异步客户端

    在公司内部的微服务架构中有使用到了"ZooKeeper",虽然官方有提供了.NET的SDK,但易用性非常的差,且搜遍github.nuget,没有发现一个可以跨平台且易用的组件,所 ...

  4. Java中Properties类的操作配置文件

    知识学而不用,就等于没用,到真正用到的时 候还得重新再学.最近在看几款开源模拟器的源码,里面涉及到了很多关于Properties类的引用,由于Java已经好久没用了,而这些模拟器大多用 Java来写, ...

  5. ASP.NET 操作配置文件

    1.配置文件的各种操作 http://www.cnblogs.com/shimeng3344518/archive/2007/04/23/723999.html 2. http://www.jb51. ...

  6. QSettings操作配置文件

    用Qt写界面时,难免会进行本地信息的保存,可以使用轻量级数据库sqlite,也可以使用QSettings读写配置文件.     如何来进行读写呢?如下,使用QSettings写一个通用的读写方法:   ...

  7. 使用纯生js操作cookie

    前段时间做项目的时候要使用js操作cookie,jquery也有相应的插件,不过还是觉得纯生的js比较好,毕竟不依赖jq. //获得coolie 的值 function cookie(name) { ...

  8. Python操作配置文件configparser模块

    在实际的开发过程中,我们常有操作ini格式和conf格式配置文件的操作,Python为我们提供了configparser模块,方便我们对配置文件进行读写操作. config.ini配置文件内容如下: ...

  9. kbmmw 中XML 操作入门(跨平台,而且可以与JSON,YAML,BSON 直接互相转换)

    delphi 很早以前就自带了xml 的操作,最新版里面有三种XML 解释器,一种是MSXML,看名字就知道 这个是微软自带的,这个据delphi 官方称是速度是最快的,但是只能在windows 上使 ...

随机推荐

  1. 判断声明出来的list为空的时候,list!=null

    判断声明出来的list为空的时候,listjcxm!=null&&listjcxm.size()==0: 有时候list不为null但是size为0 map也是类似

  2. Selenium: 利用select模块操作下拉框

    在利用selenium进行UI自动化测试过程中,经常会遇到下拉框选项,这篇博客,就介绍下如何利用selenium的Select模块来对标准select下拉框进行操作... 首先导入Select模块: ...

  3. window.postMessage 跨窗口,跨iframe javascript 通信

    同源通信 执行它们的页面位于具有相同的协议(http/https),端口(80/443),主机(通常为域名) 时,这两个脚本才能相互通信 大多数情况下,网站就是内部的域名,所以是同源通信,可以相互访问 ...

  4. Windows安装Centos7双系统后Windows启动项消失

    原文: https://www.cnblogs.com/xinglichao/p/9999049.html https://blog.csdn.net/yingzinanfei/article/det ...

  5. 超详细Qt5.9.5移植攻略

    本文就来介绍下如何将Qt5.9.5移植到ARM开发板上. 以imx6开发板为例,使用Ubuntu14.04虚拟机作为移植环境. 准备工作 1.主机环境:Ubuntu14.04: 开发板:启扬IAC-I ...

  6. springboot之freemarker 和thymeleaf模板web开发

    Spring Boot 推荐使用Thymeleaf.FreeMarker.Velocity.Groovy.Mustache等模板引擎.不建议使用JSP. 一.Spring Boot 中使用Thymel ...

  7. shell统计ip访问情况并分析访问日志

    有日志 1.log,部分内容如下: 112.111.12.248 – [25/Sep/2013:16:08:31 +0800]formula-x.haotui.com“/seccode.php?upd ...

  8. Docker,就放弃了把日志写入文件

    日志配置 既然用 Docker,就放弃了把日志写入文件,直接写到标准输出. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ...

  9. com.alibaba.fastjson.JSONObject;的使用

    转: com.alibaba.fastjson.JSONObject;的使用 2018-11-04 23:51:23 mameng1998 阅读数 6404更多 分类专栏: java   1  POM ...

  10. 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_20-认证接口开发-接口测试

    测试接口 因为继承了spring  security会拦截这个请求,我们需要写代码 让他对这个认证接口放行 查看代码发现之前已经写过放行的代码了 发现是路径前面少了auth 加断点,测试.申请令牌 r ...