大部分的项目都会用到配置文件,之前也有一个一直在用的读取配置文件的代码,感觉不是太好。也奉献上来吧
static bool readConfigFile(const char* configFilePath,const string key,string &value)
{
fstream cfgFile;
cfgFile.open(configFilePath,ios::in);
if(!cfgFile.is_open())
{
cout<<"打开文件失败!"<<endl;
return false;
}
char buf[1000]={0};
while (!cfgFile.eof())
{
cfgFile.getline(buf,1000); //每行读取前1000个字符
string line(buf);
size_t pos=line.find("="); //找到每行的“=”位置,之后的是value
if (pos==string::npos) //查找到最后没有了
{
return false;
}
string beforeValue=line.substr(0,pos);
//cout<<beforeValue<<":";
if (key==beforeValue)
{
value=line.substr(pos+1);
//cout<<value<<endl;
}
}
cfgFile.close();
return false;
}
于是找轮子造了一个自行车。直接撸代码。
readConfigFile.h
#ifdef WIN32
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#pragma warning(disable:4996)
#else
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define MAX_PATH 260
#endif
#define CONF_FILE_PATH "conf.ini"
#define MAX_BUF 1024
//获取当前程序目录
int getCurrentPath(char buf[],char *pFileName);
//从配置文件读取字符串类型数据
int readConfigFile_String(char *filename, char *title,char *key,char *value);
//从配置文件读取整类型数据
int readConfigFile_Int(char *filename,char *title,char *key);
readConfigFile.cpp
#include "readConfigFile.h"
char g_szConfigPath[MAX_PATH]={0};
//获取当前程序目录
int getCurrentPath(char buf[],char *pFileName)
{
#ifdef WIN32
GetModuleFileName(NULL,buf,MAX_PATH);
#else
char pidfile[64]={0};
int bytes=0;
int fd=0;
sprintf(pidfile, "/proc/%d/cmdline", getpid());
fd = open(pidfile, O_RDONLY, 0);
bytes = read(fd, buf, 256);
close(fd);
buf[MAX_PATH] = '\0';
#endif
char * p = &buf[strlen(buf)];
do
{
*p = '\0';
p--;
#ifdef WIN32
} while( '\\' != *p );
#else
} while( '/' != *p );
#endif
p++;
//配置文件目录
memcpy(p,pFileName,strlen(pFileName));
return 0;
}
//从配置文件读取字符串类型数据
int readConfigFile_String(char *filename, char *title,char *key,char *value)
{
FILE *fp=NULL;
char szLine[MAX_BUF]={0};
static char tmpstr[MAX_BUF]={0};
int rtnval=0;
int i = 0;
int flag = 0;
char *tmp=NULL;
bool isFirst=true; //是否为第一次扫描配置文件
bool isEnd=false; //是否扫描完配置文件
if((fp = fopen(filename, "r")) == NULL)
{
printf("没有找到配置文件:%s\n",filename);
return -1;
}
while(!feof(fp))
{
if (isEnd) break; //扫描配置文件结束
rtnval = fgetc(fp);
if(rtnval == EOF)
{
isEnd=true;
}
else
{
szLine[i++] = rtnval;
}
if(rtnval == '\n'||isFirst==true||isEnd==true) //第一次扫描配置文件 第一行不用是\n
{
if (isFirst==false&&isEnd!=true) //是否为第一次扫描文件
{
szLine[--i] = '\0';
i = 0;
}
tmp = strchr(szLine, '=');
if(( tmp != NULL )&&(flag == 1))
{
if(strstr(szLine,key)!=NULL)
{
//注释行
if ('#' == szLine[0]) //#注释 如#href=0.0.0.0
{
}
else if ( '\/' == szLine[0] && '\/' == szLine[1] ) //#注释 如//age=25
{
}
else
{
//找到key对应变量
strcpy(value,tmp+1);
fclose(fp);
return 0;
}
}
else
{
memset(szLine,0,MAX_BUF);
}
}
else
{
strcpy(tmpstr,"[");
strcat(tmpstr,title);
strcat(tmpstr,"]");
if( strncmp(tmpstr,szLine,strlen(tmpstr)) == 0 )
{
//找到title
flag = 1;
}
}
isFirst=false;
}
}
fclose(fp);
return -1;
}
//从配置文件读取整类型数据
int readConfigFile_Int(char *filename,char *title,char *key)
{
char value_string[MAX_BUF]={0};
if(readConfigFile_String(filename,title,key,value_string)==0) //成功
{
return atoi(value_string);
}
else //失败
{
return -1;
}
}
int main(int argc, char* argv[])
{
char buf[MAX_PATH]={0};
memset(buf,0,sizeof(buf));
getCurrentPath(buf,CONF_FILE_PATH);
strcpy(g_szConfigPath,buf);
printf("path:%s\n",g_szConfigPath);
int age=-1;
char href[32]={0};
if (readConfigFile_String(g_szConfigPath,"CAT","href",href)!=0)
{
printf("未找到所对应key的值\n");
}
printf("href:%s\n",href);
age=readConfigFile_Int(g_szConfigPath,"CAT","age");
if (age==-1)
{
printf("未找到所对应key的值\n");
}
printf("age:%d\n",age);
#ifdef WIN32
system("pause");
#endif // WIN32
return 0;
}
配置文件内容
conf.ini
[CAT]
href=192.168.0.109:8080
#href=192.168.0.109:8080
//age=25
age=100
VS2012运行结果
Linux运行结果
改进说明: 主要改进的就是换行才能获取到数据,之前的这个要求很鸡肋啊,用着太不方便了。