《文件篇》读写ini文件

读写ini文件

法一

原文链接:https://blog.csdn.net/elikang/article/details/85326597

配置文件Config.ini:

[test]
name=elikang
age=12

代码:

// HB_LED_002.cpp : Defines the entry point for the console application.
//

//#include <unistd.h>
#include <stdio.h>

#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdarg.h>

//read string from config file
char *get_string_from_ini(char *title, char *key, char *filename)
{
	FILE *fp;
	char szLine[1024];
	static char tmpstr[1024] = {'\0'};
	int rtnval;
	int i = 0;
	int flag = 0;
	char *tmp;

	if((fp = fopen(filename, "r")) == NULL)
	{
		perror("fopen()");
		return NULL;
	}

	while(!feof(fp))
	{
		rtnval = fgetc(fp);

		if(rtnval == EOF)
		{
			break;
		}
		else
		{
			szLine[i++] = rtnval;
		}

		if(rtnval == '\n')
		{
			szLine[--i] = '\0';
			i = 0;

			// temp指向每行的第一个=
			tmp = strchr(szLine, '=');

			if((tmp != NULL) && (flag == 1))
			{
				if(strstr(szLine, key) != NULL)
				{
					//comment
					if('#' == szLine[0]);
					else if('/' == szLine[0] && '/' == szLine[1]);
					else
					{
					//local key position
					strcpy(tmpstr, tmp+1);

					fclose(fp);
					return tmpstr;
					}
				}
			}
			else
			{
				strcpy(tmpstr, "[");
				strcat(tmpstr, title);
				strcat(tmpstr, "]");

				if(strncmp(tmpstr, szLine, strlen(tmpstr)) == 0)
				{
					//encounter title
					flag = 1;
				}
			}
		}
	}

	fclose(fp);
	return "";
}

int get_int_from_ini(char *title, char *key, char *filename)
{
	return atoi(get_string_from_ini(title, key, filename));
}

int main(int argc, char **argv)
{
	char name[1024];
	int age = 0;

	char file_path[20] = "./Config.ini";

	printf("file_path: %s\n", file_path);

	memset(name, 0, sizeof(name));

	age = get_int_from_ini("test", "age", file_path);
	strcpy(name, get_string_from_ini("test", "name", file_path));

	//puts(name);
	printf("%s", name);
	printf("age=%d\n", age);
}

法二

原文链接:https://www.jb51.net/article/225603.htm

什么是ini?

ini 文件是Initialization File的缩写,即初始化文件,这是用来配置应用软件以实现不同用户的要求。

INI文件的格式:

INI文件由节、键、值组成。
一个简单的的INI文件例子如下:

[Setting]
INIT_FLAG=0;
VOLUME=1;
LANGUAGE=1;

如上例子,[Setting]就是节,=号左边的值是键,=号右边的是值。

解析代码:

ini.h

/*ini.h*/
#ifndef INI_H
#define INI_H
#include <stdio.h>
#include <string.h>
int GetIniKeyString(char *title,char *key,char *filename,char *buf);
int PutIniKeyString(char *title,char *key,char *val,char *filename);
#endif /*INI_H*/

ini.c

/*ini.c*/
#include <stdio.h>
#include <string.h>
/*
	* 函数名:         GetIniKeyString
	* 入口参数:        title
	*                      配置文件中一组数据的标识
	*                  key
	*                      这组数据中要读出的值的标识
	*                  filename
	*                      要读取的文件路径
	* 返回值:         找到需要查的值则返回正确结果 0
	*                  否则返回-1
	*/
int GetIniKeyString(char *title,char *key,char *filename,char *buf)
{
	FILE *fp;
	int  flag = 0;
	char sTitle[64], *wTmp;
	char sLine[1024];
	sprintf(sTitle, "[%s]", title);

	if(NULL == (fp = fopen(filename, "r"))) {
		perror("fopen");
		return -1;
	}
	while (NULL != fgets(sLine, 1024, fp)) {
		// 这是注释行
		if (0 == strncmp("//", sLine, 2)) continue;
		if ('#' == sLine[0])              continue;
		wTmp = strchr(sLine, '=');
		if ((NULL != wTmp) && (1 == flag)) {
			if (0 == strncmp(key, sLine, strlen(key))) { // 长度依文件读取的为准
				sLine[strlen(sLine) - 1] = '\0';
				fclose(fp);
				while(*(wTmp + 1) == ' '){
					wTmp++;
				}
				strcpy(buf,wTmp + 1);
				return 0;
			}
		} else {
			if (0 == strncmp(sTitle, sLine, strlen(sTitle))) { // 长度依文件读取的为准
				flag = 1; // 找到标题位置
			}
		}
	}
	fclose(fp);
	return -1;
}

/*
	* 函数名:         PutIniKeyString
	* 入口参数:        title
	*                      配置文件中一组数据的标识
	*                  key
	*                      这组数据中要读出的值的标识
	*                  val
	*                      更改后的值
	*                  filename
	*                      要读取的文件路径
	* 返回值:         成功返回  0
	*                  否则返回 -1
	*/
int PutIniKeyString(char *title,char *key,char *val,char *filename)
{
	FILE *fpr, *fpw;
	int  flag = 0;
	char sLine[1024], sTitle[32], *wTmp;
	sprintf(sTitle, "[%s]", title);
	if (NULL == (fpr = fopen(filename, "r")))
		return -1;// 读取原文件
	sprintf(sLine, "%s.tmp", filename);
	if (NULL == (fpw = fopen(sLine,    "w")))
		return -1;// 写入临时文件
	while (NULL != fgets(sLine, 1024, fpr)) {
		if (2 != flag) { // 如果找到要修改的那一行,则不会执行内部的操作
			wTmp = strchr(sLine, '=');
			if ((NULL != wTmp) && (1 == flag)) {
				if (0 == strncmp(key, sLine, strlen(key))) { // 长度依文件读取的为准
					flag = 2;// 更改值,方便写入文件
					sprintf(wTmp + 1, " %s\n", val);
				}
			} else {
				if (0 == strncmp(sTitle, sLine, strlen(sTitle))) { // 长度依文件读取的为准
					flag = 1; // 找到标题位置
				}
			}
		}
		fputs(sLine, fpw); // 写入临时文件
	}
	fclose(fpr);
	fclose(fpw);
	sprintf(sLine, "%s.tmp", filename);
	return rename(sLine, filename);// 将临时文件更新到原文件
}

上述两个函数是简单的解析函数,因为ini文件有很多种解析方式,根据不同的需求解析也不同
所以要进行修改
比如我的注释符号是 “ ;”,所以我需要修改

image

并且根据实际功能需求也可以进行进一步的封装

测试如下

ini样本

/*test.ini*/
[city]
beijing =  hello-beijing
shanghai = hello-shanghai


#information
[study]
highschool = xxxx
university = yyyy

程序

/*test.c*/
#include "ini.h"
#include <stdio.h>
int main(int argc, char const *argv[])
{
	char buff[100];
	int ret;

	ret = GetIniKeyString("city","beijing","./test.ini",buff);
	printf("ret:%d,%s\n",ret,buff);

	ret = GetIniKeyString("study","highschool","./test.ini",buff);
	printf("ret:%d,%s\n",ret,buff);

	ret = PutIniKeyString("study","highschool","zzzz","./test.ini");
	printf("put ret:%d\n",ret);
	ret = GetIniKeyString("study","highschool","./test.ini",buff);
	printf("ret:%d,%s\n",ret,buff);
	return 0;
}

结果如下:

ret:0,hello-beijing
ret:0,xxxx
put ret:0
ret:0,zzzz
posted @ 2023-03-30 12:31  Fusio  阅读(22)  评论(0编辑  收藏  举报