https://www.jianshu.com/p/01a5a4b1aba9
config_stream.h
#ifndef _CONFIG_STREAM_H__
#define __CONFIG_STREAM_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
*file_absolute_path 文件绝对路径(in)
*key 要查询的键(in)
**value 输出的键值(out)
*len 键值长度(in)
*/
int intput_config_value(char *file_absolute_path,char *key,char **value,int *len);
/**
*file_absolute_path 文件绝对路径(in)
*key 要增加的键(in)
*value 要增加的键值(in)
*/
int output_config_key_value(char *file_absolute_path, char *key, char *value);
#ifdef __cplusplus
}
#endif
#endif
config_stream.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/* 行缓冲大小 */
#define MaxLine 1024
//读键值
int intput_config_value(char *file_absolute_path, char *key, char **value, int *len) {
int ret = 1;
FILE *file = NULL; //文件流
char lineBuf[MaxLine] = {0};//行缓冲
char *tempP = NULL; // 临时字符串指针
char *start = NULL; //键值开始位置
char *end = NULL; //键值结束位置
char *tempValue = NULL;
if (file_absolute_path == NULL || key == NULL || value == NULL) {
ret = -1;
goto END;
}
//读取文件
file = fopen(file_absolute_path,"r");
if (file == NULL) {
ret = -2;
goto END;
}
while (!feof(file))
{
memset(lineBuf,0,sizeof(lineBuf));
//读取行
tempP = fgets(lineBuf,MaxLine,file);
//是否有"="
tempP = strchr(lineBuf,'=');
if (tempP == NULL) {
//没有读取到键值
continue;
}
//判断是否此行有包含我要的key
tempP = strstr(lineBuf,key);
if (tempP == NULL) {
continue;
}
//获取值
tempP = strchr(lineBuf, '=');
//+1超过'='位置
tempP = tempP + 1;
while (1)
{
if (*tempP == ' ') {
tempP++;
}
else {
start = tempP;
if (*start == '\n') { //表示只有键 没有键值的情况
ret = -3;
goto END;
}
break;
}
}
while (1) {
if ((*tempP == ' ' || *tempP == '\n')) {
break;
}
else {
tempP++;
}
}
end = tempP;
//计算出value长度
//*len = end - start;//内存溢出
*len = (end - start) + 1;
tempValue = (char*)malloc(*len * sizeof(char));
bzero(tempValue, *len);
memcpy(tempValue, start, *len);
*value = tempValue;
break;
}
END:
if (file != NULL) {
fclose(file);
}
return ret;
}
//写键值
int output_config_key_value(char *file_absolute_path, char *key, char *value) {
/*
有一个大的文件数据缓冲,将数据按行从文件读出,如果有找到对应的键就将值修改并且将重新创建文件把文件数据缓冲区的数据写入文件
,不存在键则在文件末尾增加键值
*/
int ret = 1;
FILE *file = NULL;//文件流
int fileLength;//文件长度
char lineBuf[MaxLine] = {0};//行数据缓冲
char fileBuf[MaxLine * 10] = {0};//文件数据缓冲
char *tempP = NULL;//用于记录每次读取到的指针位置(即读取到的字符串)
char *tempKey = NULL;
int flag = 0;
if (file_absolute_path == NULL || key == NULL || value == NULL) {
ret = -1;
goto END;
}
tempKey = key;
//r+具有读写属性,从文件头开始写,保留原文件中没有被覆盖的内容;
file = fopen(file_absolute_path,"r+");
if (file == NULL) {
//说明文件不存在,创建文件
//“w+t” 只写打开或建立一个文本文件,只允许写数据
file = fopen(file_absolute_path, "w+t");
if (file == NULL) {
ret = -2;
goto END;
}
}
//跳到文件末尾
fseek(file,0L,SEEK_END);
//获取文件长度
fileLength = ftell(file);
//跳回文件开始
fseek(file,0L,SEEK_SET);
while (!feof(file))
{
//初始化行缓冲
memset(lineBuf,0,sizeof(lineBuf));
//读取行 -->> 文件流file中读取到lineBuf中 tempP是读取到的字符串首地址
tempP = fgets(lineBuf,MaxLine,file);
if (tempP == NULL) {
break;
}
//该行字符串是否包含key
tempP = strstr(lineBuf,tempKey);
if (tempP == NULL) {
//不包含key,将这行存进文件缓冲
strcat(fileBuf,lineBuf);
continue;
}
else {
//包含了key,需要将此行替换后考入文件缓冲
sprintf(lineBuf,"%s = %s\n",key,value);
strcat(fileBuf,lineBuf);
flag = 1;
}
}
if (flag == 0) {
//key不存在追加一行
fprintf(file,"%s = %s\n",key,value);
}
else {
//key 存在,重新创建文件将文件缓冲中的内容写进去
if (file != NULL) {
fclose(file);
}
file = fopen(file_absolute_path,"w+t");
if (file == NULL) {
ret = -2;
goto END;
}
//将文件缓冲区数据写进文件
fputs(fileBuf,file);
}
END:
if (file != NULL) {
fclose(file);
}
return ret;
}
config_test.c测试文件
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "config_stream.h"
/* 文件绝对路径 */
#define FILE_ABS_PATH "/tmp/volume.conf"
void main(int argc, char **argv) {
char *key = "volume";
char value[50] = "20";
int len;
char *values = NULL;
int ret;
int ret2;
int val;
//写
if(argc == 2) {
ret2 = intput_config_value(FILE_ABS_PATH,key,&values,&len);
//printf("value=%s\nlen=%d\n",values,len);
if (argv[1][0] == '+') {
val = atoi(values)+1;
if (val > 10) {
val = 10;
}
sprintf(value, "%d", val);
} else {
val = atoi(values)-1;
if (val < 0) {
val = 0;
}
sprintf(value, "%d", val);
}
ret = output_config_key_value(FILE_ABS_PATH,key,value);
printf("ret=%d value=%s\n",ret, value);
free(values);
} else {
//读
ret2 = intput_config_value(FILE_ABS_PATH,key,&values,&len);
printf("value=%s\nlen=%d\n",values,len);
free(values);
}
}