配置文件的读取
- 使用配置文件,我们的服务器程序有了极大的灵活性;
- 配置文件:文本文件,里面除了注释外不要使用中文(仅使用字母、数字、下划线);
- 以#开头的行作为注释行
- 项目的首要任务是将配置文件中的配置项读到内存中;
#pragma once
#include <vector>
typedef struct
{
char ItemName[50];
char ItemContent[500];
}CConfItem, *LPCConfItem;
class CConfig
{
private:
CConfig();
public:
~CConfig();
static CConfig* m_instance;
public:
static CConfig* GetInstance()
{
if (m_instance == NULL)
{
m_instance = new CConfig();
static CGrecycle cg;
}
return m_instance;
}
class CGrecycle
{
public:
~CGrecycle()
{
if (CConfig::m_instance)
{
delete CConfig::m_instance;
CConfig::m_instance = NULL;
}
}
};
public:
bool Load(const char *pconfName);
const char *GetString(const char *p_itemname);
int GetIntDefault(const char *p_itemname, const int def);
public:
std::vector<LPCConfItem> m_ConfigItemList;
};
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include "readconf.h"
static CConfig* m_instance = NULL;
CConfig::CConfig()
{
}
CConfig::~CConfig()
{
std::vector<LPCConfItem>::iterator pos;
for (pos = m_ConfigItemList.begin(); pos != m_ConfigItemList.end(); ++pos)
{
delete(*pos);
}
m_ConfigItemList.clear();
}
bool CConfig::Load(const char* pconfName)
{
FILE* fp;
fp = fopen(pconfName, "r");
if (fp == NULL)
return false;
char linebuf[501] = { 0 };
while (!feof(fp))
{
if (fgets(linebuf, 500, fp) == NULL)
continue;
if (linebuf[0] == 0)
continue;
if (*linebuf == ';' || *linebuf == ' ' || *linebuf == '#' || *linebuf == '\t' || *linebuf == '\n')
continue;
JumpToHere:
if (linebuf[strlen(linebuf) - 1] == 10 || linebuf[strlen(linebuf) - 1] == 13 || linebuf[strlen(linebuf) - 1] == 32)
{
linebuf[strlen(linebuf) - 1] = 0;
goto JumpToHere;
}
if (linebuf[0] == 0)
continue;
if (*linebuf == '[')
continue;
char* ptemp = strchr(linebuf, '=');
if (ptemp != NULL)
{
LPCConfItem p_ConfItem = new CConfItem();
memset(p_ConfItem, 0, sizeof(CConfItem));
strncpy(p_ConfItem->ItemName, linebuf, (int)(ptemp - linebuf));
strcpy(p_ConfItem->ItemContent, ptemp + 1);
Rtrim(p_ConfItem->ItemName);
Ltrim(p_ConfItem->ItemName);
Rtrim(p_ConfItem->ItemContent);
Ltrim(p_ConfItem->ItemContent);
m_ConfigItemList.push_back(p_ConfItem);
}
}
fclose(fp);
return true;
}
const char *CConfig::GetString(const char *p_itemname)
{
std::vector<LPCConfItem>::iterator pos;
for (pos = m_ConfigItemList.begin(); pos != m_ConfigItemList.end(); ++pos)
{
if (stricmp((*pos)->ItemContent, p_itemname) == 0)
{
return (*pos)->ItemContent;
}
}
return NULL;
}
int CConfig::GetIntDefault(const char *p_itemname, const int def)
{
std::vector<LPCConfItem>::iterator pos;
for (pos = m_ConfigItemList.begin(); pos != m_ConfigItemList.end(); ++pos)
{
if (stricmp((*pos)->ItemContent, p_itemname) == 0)
{
return atoi((*pos)->ItemContent);
}
}
return def;
}
void Rtrim(char* string)
{
if (string = NULL) return;
size_t len = 0;
len = strlen(string);
while (len > 0 && string[len - 1] == ' ')
{
string[--len] = 0;
}
return;
}
void Ltrim(char* string)
{
size_t len = 0;
len = strlen(string);
char *p_tmp = string;
if ((*p_tmp) != ' ')
return;
while ((*p_tmp) != '\0')
{
if ((*p_tmp) == ' ')
p_tmp++;
else
break;
}
if ((*p_tmp) == '\0')
{
*string = '\0';
return;
}
char *p_tmp2 = string;
while ((*p_tmp) != '\0')
{
(*p_tmp2) = (*p_tmp);
p_tmp++;
p_tmp2++;
}
(*p_tmp2) = '\0';
return;
}
- 这样在main函数中,我们就可以方便地将配置文件载入内存:
int main(int argc, char* const *argv)
{
CConfig* p_config = CConfig::GetInstance();
if (p_config->Load("nginx.conf") == false)
{
printf("配置文件载入失败,退出!\n");
exit(1);
}
return 0;
}