C/C++ INI文件操作实现代码

 更新时间:2020年02月05日 20:55:52   作者:烈风  
本文章主要为分享C/C++ INI文件操作实现代码,增加注释和修复了一些问题。这里给出完整的实现文件,在需要的地方包含该头文件就好了

一、INI文件用途:

1、存储程序的初始化信息;
2、存储需要保存的数据信息。

二、INI文件结构:

由节名、键名、键值组成。形式如下:
[节名]
键名 = 键值

备注:一个INI文件,可以用多个节。

三、读取INI文件

1、WritePrivateProfileString

该函数用于向INI文件中写入一个字符串数据。

函数原型如下:

BOOL WritePrivateProfileString(
 LPCTSTR lpAppName, // pointer to section name
 LPCTSTR lpKeyName, // pointer to key name
 LPCTSTR lpString, // pointer to string to add
 LPCTSTR lpFileName // pointer to initialization filename
);

参数说明:

lpAppName:指定节名,以空终止结尾的字符串。如果INI文件中节名不存在,将创建一个节名。
lpKeyName:键名,以空终止结尾的字符串。如果INI文件中该键名不存在,将创建一个键名。如果该参数为NULL,包括节及节下的所有项目都将被删除。
lpString:写到键值中的数据,以空终止结尾的字符串。
lpFileName:INI文件的名称,以空终止结尾的字符串。指定需要写入数据的INI文件,如果指定的INI文件不存在将创建。

返回值:

如果函数成功将字符串复制到初始化文件,返回值是非零。
如果函数失败,刷新缓存版本的最近访问初始化文件,返回值是零。

2、GetPrivateProfileString

该函数用于获取INI文件中的键值。
函数原型如下:

DWORD GetPrivateProfileString(
 LPCTSTR lpAppName, // points to section name
 LPCTSTR lpKeyName, // points to key name
 LPCTSTR lpDefault, // points to default string
 LPTSTR lpReturnedString, // points to destination buffer
 DWORD nSize, // size of destination buffer
 LPCTSTR lpFileName // points to initialization filename
);

参数说明:

lpAppName:指定节名,以空终止结尾的字符串。如果该参数为NULL,函数将复制所有的节名到所指定的缓冲区中。
lpKeyName:键名,以空终止结尾的字符串。如果该参数为NULL,函数将lpAppName节下所有的键名复制到lpReturnedString缓冲区。
lpDefault:默认值,以空终止结尾的字符串。如果获取键值的键名不存在时,返回设置的默认值。
lpReturnedString:用于接受数据的缓冲区。
nSize:以字符为单位表示lpReturnedString缓冲区的大小。
lpFileName:INI文件名称,以空终止结尾的字符串。

返回值:
返回值是字符复制到缓冲区的数量,不包括终止null字符。

3、GetPrivateProfileInt

该函数用于从INI文件中获取整型数据。
函数原型如下:

UINT GetPrivateProfileInt( LPCTSTR lpAppName, // address of section name
 LPCTSTR lpKeyName, // address of key name
 INT nDefault, // return value if key name is not found
 LPCTSTR lpFileName // address of initialization filename
);

参数说明:
lpAppName:节名。
lpKeyName:键名。
nDefault:默认值。
lpFileName:INI文件名称。

返回值:

函数返回实际读取的整数值。

4、GetPrivateProfileSectionNames

该函数用于返回INI文件中的所有节名。
函数原型如下:

DWORD GetPrivateProfileSectionNames(
 LPTSTR lpszReturnBuffer, // address of return buffer
 DWORD nSize, // size of return buffer
 LPCTSTR lpFileName // address of initialization filename
);

参数说明:
lpszReturnBuffer:接受节名的数据缓冲区。
nSize:缓冲区的大小。
lpFileName:INI文件名称。
返回值:
返回值指定数量的字符复制到指定的缓冲,不包括终止null字符。
如果缓冲区没有大到足以包含所有相关的部分名称指定的初始化文件,返回值等于指定的长度nSize - 2。

5、GetPrivateProfileSection

该函数用于获取指定节下的所有的键名和键值。
函数原型如下:

DWORD GetPrivateProfileSection(
 LPCTSTR lpAppName, // address of section name
 LPTSTR lpReturnedString, // address of return buffer
 DWORD nSize, // size of return buffer
 LPCTSTR lpFileName // address of initialization filename
);

参数说明:

lpAppName:节名。
lpReturnedString:用于接受数据的缓冲区。
nSize:缓冲区的大小。
lpFileName:INI文件名称。
返回值:
返回值指定数量的字符复制到缓冲区,不包括终止null字符。
如果缓冲区没有大到足以包含所有与指定相关联的键名称和值对部分,返回值等于nSize - 2。

四、C++实现INI文件读写完整代码

CMyINI.h

#pragma once
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cstdlib>
#include <map>
 
using namespace std;
 
//INI文件结点存储结构
class ININode
{
public:
	ININode(string root, string key, string value)
	{
		this->root = root;
		this->key = key;
		this->value = value;
	}
	string root;
	string key;
	string value;
};
 
//键值对结构体
class SubNode
{
public:
	void InsertElement(string key, string value)
	{
		sub_node.insert(pair<string, string>(key, value));
	}
	map<string, string> sub_node;
};
 
//INI文件操作类
class CMyINI
{
public:
	CMyINI();
	~CMyINI();
 
public:
	int ReadINI(string path);													//读取INI文件
	string GetValue(string root, string key);									//由根结点和键获取值
	vector<ININode>::size_type GetSize(){ return map_ini.size(); }				//获取INI文件的结点数
	vector<ININode>::size_type SetValue(string root, string key, string value);	//设置根结点和键获取值
	int WriteINI(string path);			//写入INI文件
	void Clear(){ map_ini.clear(); }	//清空
	void Travel();						//遍历打印INI文件
private:
	map<string, SubNode> map_ini;		//INI文件内容的存储变量
};

CMyINI.cpp

#include "StdAfx.h"
#include "MyINI.h"
 
#define INIDEBUG
 
CMyINI::CMyINI()
{
}
 
 
CMyINI::~CMyINI()
{
}
 
//************************************************************************
// 函数名称: 	TrimString
// 访问权限: 	public 
// 创建日期:		2017/01/05
// 创 建 人:		
// 函数说明:		去除空格
// 函数参数: 	string & str	输入的字符串
// 返 回 值: 	std::string &	结果字符串
//************************************************************************
string &TrimString(string &str)
{
	string::size_type pos = 0;
	while (str.npos != (pos = str.find(" ")))
		str = str.replace(pos, pos + 1, "");
	return str;
}
 
//************************************************************************
// 函数名称: 	ReadINI
// 访问权限: 	public 
// 创建日期:		2017/01/05
// 创 建 人:		
// 函数说明:		读取INI文件,并将其保存到map结构中
// 函数参数: 	string path	INI文件的路径
// 返 回 值: 	int
//************************************************************************
int CMyINI::ReadINI(string path)
{
	ifstream in_conf_file(path.c_str());
	if (!in_conf_file) return 0;
	string str_line = "";
	string str_root = "";
	vector<ININode> vec_ini;
	while (getline(in_conf_file, str_line))
	{
		string::size_type left_pos = 0;
		string::size_type right_pos = 0;
		string::size_type equal_div_pos = 0;
		string str_key = "";
		string str_value = "";
		if ((str_line.npos != (left_pos = str_line.find("["))) && (str_line.npos != (right_pos = str_line.find("]"))))
		{
			//cout << str_line.substr(left_pos+1, right_pos-1) << endl;
			str_root = str_line.substr(left_pos + 1, right_pos - 1);
		}
 
		if (str_line.npos != (equal_div_pos = str_line.find("=")))
		{
			str_key = str_line.substr(0, equal_div_pos);
			str_value = str_line.substr(equal_div_pos + 1, str_line.size() - 1);
			str_key = TrimString(str_key);
			str_value = TrimString(str_value);
			//cout << str_key << "=" << str_value << endl;
		}
 
		if ((!str_root.empty()) && (!str_key.empty()) && (!str_value.empty()))
		{
			ININode ini_node(str_root, str_key, str_value);
			vec_ini.push_back(ini_node);
			//cout << vec_ini.size() << endl;
		}
	}
	in_conf_file.close();
	in_conf_file.clear();
 
	//vector convert to map
	map<string, string> map_tmp;
	for (vector<ININode>::iterator itr = vec_ini.begin(); itr != vec_ini.end(); ++itr)
	{
		map_tmp.insert(pair<string, string>(itr->root, ""));
	}	//提取出根节点
	for (map<string, string>::iterator itr = map_tmp.begin(); itr != map_tmp.end(); ++itr)
	{
#ifdef INIDEBUG
		cout << "根节点: " << itr->first << endl;
#endif	//INIDEBUG
		SubNode sn;
		for (vector<ININode>::iterator sub_itr = vec_ini.begin(); sub_itr != vec_ini.end(); ++sub_itr)
		{
			if (sub_itr->root == itr->first)
			{
#ifdef INIDEBUG
				cout << "键值对: " << sub_itr->key << "=" << sub_itr->value << endl;
#endif	//INIDEBUG
				sn.InsertElement(sub_itr->key, sub_itr->value);
			}
		}
		map_ini.insert(pair<string, SubNode>(itr->first, sn));
	}
	return 1;
}
 
//************************************************************************
// 函数名称: 	GetValue
// 访问权限: 	public 
// 创建日期:		2017/01/05
// 创 建 人:		
// 函数说明:		根据给出的根结点和键值查找配置项的值
// 函数参数: 	string root		配置项的根结点
// 函数参数: 	string key		配置项的键
// 返 回 值: 	std::string		配置项的值
//************************************************************************
string CMyINI::GetValue(string root, string key)
{
	map<string, SubNode>::iterator itr = map_ini.find(root);
	map<string, string>::iterator sub_itr = itr->second.sub_node.find(key);
	if (!(sub_itr->second).empty())
		return sub_itr->second;
	return "";
}
 
//************************************************************************
// 函数名称: 	WriteINI
// 访问权限: 	public 
// 创建日期:		2017/01/05
// 创 建 人:		
// 函数说明:		保存XML的信息到文件中
// 函数参数: 	string path	INI文件的保存路径
// 返 回 值: 	int
//************************************************************************
int CMyINI::WriteINI(string path)
{
	ofstream out_conf_file(path.c_str());
	if (!out_conf_file)
		return -1;
	//cout << map_ini.size() << endl;
	for (map<string, SubNode>::iterator itr = map_ini.begin(); itr != map_ini.end(); ++itr)
	{
		//cout << itr->first << endl;
		out_conf_file << "[" << itr->first << "]" << endl;
		for (map<string, string>::iterator sub_itr = itr->second.sub_node.begin(); sub_itr != itr->second.sub_node.end(); ++sub_itr)
		{
			//cout << sub_itr->first << "=" << sub_itr->second << endl;
			out_conf_file << sub_itr->first << "=" << sub_itr->second << endl;
		}
	}
 
	out_conf_file.close();
	out_conf_file.clear();
 
	return 1;
}
 
 
//************************************************************************
// 函数名称: 	SetValue
// 访问权限: 	public 
// 创建日期:		2017/01/05
// 创 建 人:		
// 函数说明:		设置配置项的值
// 函数参数: 	string root		配置项的根节点
// 函数参数: 	string key		配置项的键
// 函数参数: 	string value	配置项的值
// 返 回 值: 	std::vector<ININode>::size_type	
//************************************************************************
vector<ININode>::size_type CMyINI::SetValue(string root, string key, string value)
{
	map<string, SubNode>::iterator itr = map_ini.find(root);	//查找
	if (map_ini.end() != itr)
	{
		//itr->second.sub_node.insert(pair<string, string>(key, value));
		itr->second.sub_node[key] = value;
	}	//根节点已经存在了,更新值
	else
	{
		SubNode sn;
		sn.InsertElement(key, value);
		map_ini.insert(pair<string, SubNode>(root, sn));
	}	//根节点不存在,添加值
 
	return map_ini.size();
}
 
//************************************************************************
// 函数名称: 	Travel
// 访问权限: 	public 
// 创建日期:		2017/01/05
// 创 建 人:		
// 函数说明:		遍历打印INI文件
// 返 回 值: 	void
//************************************************************************
void CMyINI::Travel()
{
	for (map<string, SubNode>::iterator itr = this->map_ini.begin(); itr!= this->map_ini.end(); ++itr)
	{
		//root
		cout << "[" << itr->first << "]" << endl;
		for (map<string, string>::iterator itr1=itr->second.sub_node.begin(); itr1!=itr->second.sub_node.end();
			++itr1)
		{
			cout << " " << itr1->first << " = " << itr1->second << endl;
		}
	}
	
}

测试之前INI文件的内容:

测试程序:

CMyINI *p = new CMyINI();
p->ReadINI("Setting.ini");
cout << "\n原始INI文件内容:" << std::endl;
p->Travel();
p->SetValue("setting", "hehe", "eheh");
cout << "\n增加节点之后的内容:" << std::endl;
p->Travel();
cout << "\n修改节点之后的内容:" << std::endl;
p->SetValue("kk", "kk", "2");
p->Travel();
p->WriteINI("Setting.ini");

测试结果:

五、C++读写ini文件中的配置信息

ini文件是由若干个节(Sction)组成,每个节又由若干个键(Key)组成。
1、将文件写入ini文件中,主要使用的函数是WritePrivateProfileString(LPCWSTR IpAppName,LPCWSTR IpKeyName,LPCWSTR IpString,LPCWSTR IpFileName);
参数一表示节的名字,参数二表示键的名字,若为NULL,则删除整个节,参数三表示键的值,若为NULL,则删除这个键,参数四表示文件名。

#ifndef CONFIG_FILE
#define CONFIG_FILE (_T("Config.ini"))
#endif
TCHAR IniPath[MAX_PATH]={0}
GetModuleFileName(NULL,IniPath,Max_Path);
  TCHAR *pFind=_tcsrchr(IniPath,'\\');
if(pFind==NULL)
{
return;
}
​​​​​​​*pFind='\0';
CString newIniPath=IniPath;
newIniPath+="\\";
newIniPath+=CONFIG_FILE;

写入........

2、将ini文件中的配置信息读取出来,主要使用的函数为 GetPrivateProfileString(LPCWSTR IpAppName,LPCWSTR IpKeyName,LPCWSTR IpDefault,LPCWSTR IpReturnedString,DWORD nSize,LPCWSTR IpFileName)和GetPrivateProfileInt(LPCWSTR IpAppName,LPCWSTR IpKeyName,Int nDefault,LPCWSTR IpFileName);
 GetPrivateProfileString:参数一表示节的名字,参数二表示键的名字,参数三表示如果指定的键名不存在时所默认的读取值,参数四用来接收读取的字符串,参数五指定lpReturnedString指向的缓冲区的大小  ,参数六表示文件名。
GetPrivateProfileInt:参数一表示节的名字,参数二表示键的名字,参数三表示如果指定的键名不存在时所默认的读取值,参数四表示文件名。

TCHAR IniPath[MAX_PATH]={0};
GetModuleFileName(NULL,IniPath,Max_Path);
IniPath[_tcslen(IniPath)-1]='i'
IniPath[_tcslen(IniPath)-2]='n'
IniPath[_tcslen(IniPath)-3]='i'
if(!PathFileExists(IniPath))
{}

读取...........

相关文章

最新评论