纯C++实现操作配置文件(告别跨平台问题)
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 §ion, const string &key, string &value, string &error);
bool ModifyValue(const string §ion, const string &key, const string &value, string &error);
private:
bool OpenFile();
bool FindSection(const string §ionName);
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 §ionName)
{
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 §ion, 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 §ion, 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++实现操作配置文件(告别跨平台问题)的更多相关文章
- 操作配置文件Properties
// */ // ]]> 操作配置文件Properties Table of Contents 1 定义 2 读取配置值 3 修改和保存配置 4 注意 1 定义 csharp中在Settin ...
- day20 二十、加密模块、操作配置文件、操作shell命令、xml模块
一.加密模块 1.hashlib模块:加密 ①有解密的加密方式 ②无解密的加密方式:碰撞检查 -- 1)不同数据加密后的结果一定不一致 -- 2)相同数据的加密结果一定是一致的 import hash ...
- 支持断线重连、永久watcher、递归操作并且能跨平台(.NET Core)的ZooKeeper异步客户端
在公司内部的微服务架构中有使用到了"ZooKeeper",虽然官方有提供了.NET的SDK,但易用性非常的差,且搜遍github.nuget,没有发现一个可以跨平台且易用的组件,所 ...
- Java中Properties类的操作配置文件
知识学而不用,就等于没用,到真正用到的时 候还得重新再学.最近在看几款开源模拟器的源码,里面涉及到了很多关于Properties类的引用,由于Java已经好久没用了,而这些模拟器大多用 Java来写, ...
- ASP.NET 操作配置文件
1.配置文件的各种操作 http://www.cnblogs.com/shimeng3344518/archive/2007/04/23/723999.html 2. http://www.jb51. ...
- QSettings操作配置文件
用Qt写界面时,难免会进行本地信息的保存,可以使用轻量级数据库sqlite,也可以使用QSettings读写配置文件. 如何来进行读写呢?如下,使用QSettings写一个通用的读写方法: ...
- 使用纯生js操作cookie
前段时间做项目的时候要使用js操作cookie,jquery也有相应的插件,不过还是觉得纯生的js比较好,毕竟不依赖jq. //获得coolie 的值 function cookie(name) { ...
- Python操作配置文件configparser模块
在实际的开发过程中,我们常有操作ini格式和conf格式配置文件的操作,Python为我们提供了configparser模块,方便我们对配置文件进行读写操作. config.ini配置文件内容如下: ...
- kbmmw 中XML 操作入门(跨平台,而且可以与JSON,YAML,BSON 直接互相转换)
delphi 很早以前就自带了xml 的操作,最新版里面有三种XML 解释器,一种是MSXML,看名字就知道 这个是微软自带的,这个据delphi 官方称是速度是最快的,但是只能在windows 上使 ...
随机推荐
- docker笔记--如何批量删掉已经停止的容器
(以下操作都是在root用户) 方法如下: (1)显示所有容器,过滤出状态为Exited的容器id,然后删除. # for i in `docker ps -a |grep Exited |awk ...
- spring boot 之登录笔记
在测试平台的开发中,会牵涉到登录内容,页面需要登录后才能访问,所以,对于登录的开发是很有必要的.本文记录我在系统登录的一些自己的做法. 首先对登录进行设计. 如下: 1.登录密码输入错误超过次数限制 ...
- Zookeeper简介&应用场景
简介 将zookeeper看作一个服务,为了服务的高可靠,这个服务也是集群组成的,少数(少于n+1)机器挂掉可以通过选举产生一个leader,不会影响这个服务可用性 主要应用场景: 配置文件管理 集群 ...
- IIS部署常见错误
1.404.17 2.402.2 3.401.3 4.未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项”的解决方法
- VUE -- 对 Element UI table中数据进行二次处理
时间——日期 后台经常给我们返回的是 时间戳 (例如:1535620671) 这时候我们页面展现的时候需要将时间戳转换为我们要的格式 例如 (YYYY-MM-DD HH:mm:ss) 如果是在Elem ...
- MIPS 指令集(共31条)
MIPS 指令集(共31条) MIPS 指令集(共31条) 助记符 指令格式 示例 示例含义 操作及其解释 Bit # 31..26 25..21 20..16 15..11 10..6 5..0 R ...
- Matlab注释的几个方法
Matlab最简单的注释当然是 %x= %这是注释,无法运行 x= %结果为2 然而%只能注释一行,如何注释更加快捷简便地注释多行呢? %{ .这就是传说中的多行注释 .成功! %} 经常需要调试程序 ...
- 你的Node应用,对接分布式链路跟踪系统了吗?(一) 原创: 金炳 Node全栈进阶 4天前 戳蓝字「Node全栈进阶」关注我们哦
你的Node应用,对接分布式链路跟踪系统了吗?(一) 原创: 金炳 Node全栈进阶 4天前 戳蓝字「Node全栈进阶」关注我们哦
- React拾遗(下)
reconciliation(协调算法) react用于更新DOM的算法.基于两点假设,实现了一个启发的O(n)算法: 两个不同类型的元素将产生不同的树. 通过渲染器附带key属性,开发者可以示意哪些 ...
- IntelliJ IDEA中构建spring-boot项目
1. 打开 IDEA ,新建项目 2. 选择Spring Initializr 并在 Choose Initializr Service URL 填入 https://start.spring.io ...