1、这个IniFile是参考Delphi的Inifile来实现的。总共包括三个类:CCustomIniFile, CIniFile和CMemIniFile
其中CCustomIniFile是个抽象类,CIniFile和CMemIniFile是两个具体实现
2、CIniFile通过调用WINDOWS的GetPrivateProfileStringA和WritePrivateProfileStringA两个接口来实现。
其键值的大小有65535的限制;
3、而CMemIniFile则是存手工打造。
其基本思想就是,在创建该对象时,一次性将文件内容读取到内存中,以后所有的操作都在内存中进行。在读操作较多的情况下,使用这个实现可以具有较好的性能。当然,这个类也是允许有写操作的,不过所有的写操作如果要保存到文件中,需要调用其UpdateFile接口。
另外,该类的构造函数中还提供一个属性bCaseSensitive,用于设置是否大小写敏感,如果设置为false,则所有的section和key都不区分大小写。
其键值大小没有65535的限制;
有关细节可以参考源码。
// IniFile.h: interface for the CIniFile class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_INIFILE_H__8EB2CF67_E87C_45B4_BBF9_29981D7CE07B__INCLUDED_)
#define AFX_INIFILE_H__8EB2CF67_E87C_45B4_BBF9_29981D7CE07B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#pragma warning(disable: 4786)
#include <vector>
#include <map>
#include <set>
/************************************************************************/
/* ClassName : CCustomIniFile
/* Author : xxx
/* Date : 2008/12/17
/* Description : 基类
/************************************************************************/
class CCustomIniFile
{
public:
CCustomIniFile(CString const& fileName="");
virtual ~CCustomIniFile();
protected:
/// <summary>
/// 文件名
/// </summary>
CString m_fileName;
public:
/// <summary>
/// 清空该INI文件的内容
/// </summary>
virtual void Reset();
/// <summary>
/// 获取指定的键的字符串值
/// </summary>
virtual CString GetString(CString const& section, CString const& key, CString const& defaultValue="")=0;
/// <summary>
/// 将value转换为字符串存储在section下的key段内
/// </summary>
virtual void SetString(CString const& section, CString const& key, CString const& value)=0;
/// <summary>
/// 取得section的key键的字符串,并转换为int
/// </summary>
virtual int GetInt(CString const& section, CString const& key, int defaultValue=0);
/// <summary>
/// 将value转换为字符串存储在section下的key段内
/// </summary>
virtual void SetInt(CString const& section, CString const& key, int value);
/// <summary>
/// 取得section的key键的字符串,并转换为unsigned long
/// </summary>
virtual unsigned long GetUnsignedlong(CString const& section, CString const& key, unsigned long defaultValue = 0);
/// <summary>
/// 将value转换为字符串存储在section下的key段内
/// </summary>
virtual void SetUnsignedLong(CString const& section, CString const& key, unsigned long value);
/// <summary>
/// 取得section的key键的字符串,并转换为byte
/// </summary>
virtual byte GetByte(CString const& section, CString const& key, byte defaultValue = 0);
/// <summary>
/// 将value转换为字符串存储在section下的key段内
/// </summary>
virtual void SetByte(CString const& section, CString const& key, byte value);
/// <summary>
/// 获取bool量
/// </summary>
virtual bool GetBool(CString const& section, CString const& key, bool defaultValue = false);
/// <summary>
/// 将value转换为字符串存储在section下的key段内,true为,false 为
/// </summary>
virtual void SetBool(CString const& section, CString const& key, bool value);
/// <summary>
/// 取得section的key键的字符串,并转换为float
/// </summary>
virtual float GetFloat(CString const& section, CString const& key, float defaultValue = 0.0);
/// <summary>
/// 将value转换为字符串存储在section下的key段内
/// </summary>
virtual void SetFloat(CString const& section, CString const& key, float value);
/// <summary>
/// 取得section的key键的字符串,并转换为double
/// </summary>
virtual double GetDouble(CString const& section, CString const& key, double defaultValue = 0.0);
/// <summary>
/// 将value转换为字符串存储在section下的key段内
/// </summary>
virtual void SetDouble(CString const& section, CString const& key, double value);
/// <summary>
/// 取得section的key键下的时间,并转换为时间,时间的格式为:2006-10-10 01:02:03或-10-10 1:2:3
/// </summary>
virtual CTime GetDateTime(CString const& section, CString const& key, CTime defaultValue= CTime());
/// <summary>
/// 为section的key键设置时间
/// </summary>
virtual void SetDateTime(CString const& section, CString const& key, CTime value);
/// <summary>
/// 取得section的key键下的日期,并转换为CTime,时间的格式为:2006-10-10 00:00:00
/// </summary>
virtual CTime GetDate(CString const& section, CString const& key, CTime defaultValue= CTime());
/// <summary>
/// 为section的key键设置日期,字符串的格式为2006-10-10
/// </summary>
virtual void SetDate(CString const& section, CString const& key, CTime value);
/// <summary>
/// 取得section的key键下的日期,并转换为CTime,时间字符串的格式为: 01:11:22
/// </summary>
virtual CTime GetTime(CString const& section, CString const& key, CTime defaultValue= CTime());
/// <summary>
/// 为section的key键设置日期,时间字符串的格式为: 01:11:22
/// </summary>
virtual void SetTime(CString const& section, CString const& key, CTime value);
/// <summary>
/// 判断指定的section是否存在
/// </summary>
virtual BOOL SectionExists(CString const& section);
/// <summary>
/// 判断在指定的section内的指定的key是否存在
/// </summary>
virtual BOOL KeyExists(CString const& section, CString const& key);
/// <summary>
/// 删除指定的键
/// </summary>
virtual void DeleteKey(CString const& section, CString const& key)=0;
/// <summary>
/// 删除指定的section
/// </summary>
virtual void DeleteSection(CString const& section)=0;
/// <summary>
/// 添加一个Section
/// </summary>
virtual void AddSection(CString section)=0;
/// <summary>
/// 返回该文件内的所有section列表
/// </summary>
virtual std::vector<CString> GetSections()=0;
/// <summary>
/// 返回指定section下的key列表
/// </summary>
virtual std::vector<CString> GetKeys(CString const& section)=0;
/// <summary>
/// 读取指定section内的所有值
/// </summary>
virtual std::vector<CString> GetSectionValues(CString const& section)=0;
/// <summary>
///
/// </summary>
virtual void UpdateFile() = 0;
/// <summary>
/// 返回文件名
/// </summary>
CString GetFileName(){ return m_fileName; };
/// <summary>
/// 设置文件名
/// 文件名可以是相对路径,也可以是绝对路径
/// 如果是相对路径,则会被自动转换为相对于当前程序的绝对路径
/// </summary>
virtual void SetFileName(CString const& fileName);
protected:
BOOL FileExists();
CString GetAppPath();
};
/************************************************************************/
/* ClassName : CIniFile
/* Author : xxx
/* Date : 2008/12/17
/* Description : 用于读取文件的inifile类
1、该类所有的操作结果都马上反应到文件内,所以可以不同担心同步问题;
2、该类的ReadSection方法返回的是指定section的键名称列表,而不是该section下的所有内容
3、键值的最大长度有的限制;
/************************************************************************/
class CIniFile: public CCustomIniFile
{
public:
CIniFile(CString const& fileName="");
virtual ~CIniFile();
public:
//
virtual CString GetString(CString const& section, CString const& key, CString const& defaultValue="");
/// <summary>
/// 将value转换为字符串存储在section下的key段内
/// </summary>
virtual void SetString(CString const& section, CString const& key, CString const& value);
/// <summary>
/// 删除指定的键
/// </summary>
virtual void DeleteKey(CString const& section, CString const& key);
/// <summary>
/// 删除指定的section
/// </summary>
virtual void DeleteSection(CString const& section);
/// <summary>
/// 添加一个Section
/// </summary>
virtual void AddSection(CString section);
/// <summary>
/// 返回该文件内的所有section列表
/// </summary>
virtual std::vector<CString> GetSections();
/// <summary>
/// 返回指定section下的key列表
/// </summary>
virtual std::vector<CString> GetKeys(CString const& section);
/// <summary>
/// 读取指定section内的所有值
/// </summary>
virtual std::vector<CString> GetSectionValues(CString const& section);
/// <summary>
///
/// </summary>
virtual void UpdateFile();
private:
std::vector<CString> BufferToStringList(char* buf, int size);
};
/************************************************************************/
/* ClassName : CMemIniFile
/* Author : xxxx
/* Date : 2008/12/17
/* Description : 1、该类一次性将文件读取到内存中,以后所有的操作都在内存中进行
2、该类比较适合与读操作较多的情况
3、该类比较特殊的在于其GetSectionValues的实现,能够将一个section
下的所有内容读取出来,返回一个std::vector<CString>对象
4、该类提供了SetCaseSensitive函数,这样用户就可以选择是否大小写敏感
5、对该类所做的任何操作,如果要将操作结果保存到文件,则一定要调用UpdateFile()方法
否则所有的操作结果都只在内存中
6、键值的最大长度没有的限制;
/************************************************************************/
class CMemIniFile: public CCustomIniFile{
private:
/// <summary>
/// 用于在map的查找时使用
/// map的键类型为CString,比较方式为大小写不敏感
/// </summary>
class compare_nocase{
public:
compare_nocase(CString const& value):m_value(value){}
template<typename T1, typename T2>
bool operator()(std::pair<const T1, T2> elem){
return m_value.CompareNoCase(elem.first) == 0;
};
private:
CString m_value;
};
public:
CMemIniFile(CString const& fileName="", bool bCaseSensitive = true);
virtual ~CMemIniFile();
public:
/// <summary>
/// 设置文件名
/// </summary>
virtual void SetFileName(CString const& fileName);
/// <summary>
/// 清空该INI文件的内容
/// </summary>
virtual void Reset();
//
virtual CString GetString(CString const& section, CString const& key, CString const& defaultValue="");
/// <summary>
/// 将value转换为字符串存储在section下的key段内
/// </summary>
virtual void SetString(CString const& section, CString const& key, CString const& value);
/// <summary>
/// 删除指定的键
/// </summary>
virtual void DeleteKey(CString const& section, CString const& key);
/// <summary>
/// 删除指定的section
/// </summary>
virtual void DeleteSection(CString const& section);
/// <summary>
/// 添加一个Section
/// </summary>
virtual void AddSection(CString section);
/// <summary>
/// 返回该文件内的所有section列表
/// </summary>
virtual std::vector<CString> GetSections();
/// <summary>
/// 返回指定section下的key列表
/// </summary>
virtual std::vector<CString> GetKeys(CString const& section);
/// <summary>
/// 读取指定section内的所有值
/// </summary>
virtual std::vector<CString> GetSectionValues(CString const& section);
/// <summary>
/// 将内容保存到文件内
/// </summary>
virtual void UpdateFile();
/// <summary>
/// 判断大小写是否敏感
/// </summary>
bool GetCaseSensitive(){ return m_bCaseSensitive; };
private:
/// <summary>
/// 将文件内容读取到m_fileContent内
/// </summary>
void ReadfileContent();
/// <summary>
/// 生成索引
/// </summary>
void GenerateIndex();
private:
typedef std::map<CString, int> CSectionIndex;
typedef std::vector<CString> CFileContent;
typedef std::set<int> CSectionLineNumSet;
typedef std::map<CString, CSectionIndex > CSectionKeyIndex;
/// <summary>
/// 文件的内容
/// </summary>
CFileContent m_fileContent;
/// <summary>
/// 用于存储每个section所对应的行号
/// </summary>
CSectionIndex m_sectionIndex;
/// <summary>
/// section的行号的集合
/// </summary>
CSectionLineNumSet m_sectionLineNumSet;
/// <summary>
/// 每个section下的每个键的索引
/// </summary>
CSectionKeyIndex m_sectionKeyIndex;
/// <summary>
/// 是否大小写敏感,这是一个只读属性
/// </summary>
bool m_bCaseSensitive;
};
#endif // !defined(AFX_INIFILE_H__8EB2CF67_E87C_45B4_BBF9_29981D7CE07B__INCLUDED_)
// IniFile.cpp: implementation of the CIniFile class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "IniFile.h"
#include <algorithm>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/////////////////////////////////////////////////////////////////////////////////
//CCustomIniFile
/////////////////////////////////////////////////////////////////////////////////
CCustomIniFile::CCustomIniFile(CString const& fileName):m_fileName(fileName)
{
}
CCustomIniFile::~CCustomIniFile()
{
}
void CCustomIniFile::Reset()
{
if(m_fileName.IsEmpty())
return;
if(FileExists())
::DeleteFile(m_fileName);
CCustomIniFile::SetFileName(m_fileName);
}
BOOL CCustomIniFile::FileExists()
{
if(m_fileName.IsEmpty())
return FALSE;
CFile file;
return file.Open(m_fileName, CFile::modeRead);
}
CString CCustomIniFile::GetAppPath()
{
// 返回当前程序路径
//不包含斜干, 如c:"PQSys
char path[_MAX_PATH];
memset(path,0,sizeof(path));
::GetModuleFileName(NULL, path, sizeof(path));
CString strPath = path;
int index = strPath.ReverseFind('""');
if(index<0)
return "";
return strPath.Left(index);
}
void CCustomIniFile::SetFileName(CString const& fileName)
{
//如果是相对路径,则转换为绝对路径
if(fileName.IsEmpty())
return;
if(fileName.Find(':') != 1)
m_fileName = GetAppPath() + """" + fileName;
else
m_fileName = fileName;
if(!FileExists())
{
try
{
CFile file;
file.Open(m_fileName, CFile::modeCreate);
}
catch (CException* e)
{
UNUSED_ALWAYS(e);
TRACE("CIniFile::SetFileName() Failed!, fileName = %s", fileName);
}
}
}
int CCustomIniFile::GetInt(CString const& section, CString const& key, int defaultValue)
{
CString strValue = GetString(section, key);
if(strValue.IsEmpty())
return defaultValue;
int value(defaultValue);
try
{
value = atoi(strValue.GetBuffer(strValue.GetLength()));
strValue.ReleaseBuffer(strValue.GetLength());
}
catch (...)
{
strValue.ReleaseBuffer(strValue.GetLength());
return value;
}
return value;
}
//
void CCustomIniFile::SetInt(CString const& section, CString const& key, int value)
{
CString strValue;
strValue.Format("%d", value);
SetString(section, key, strValue);
}
unsigned long CCustomIniFile::GetUnsignedlong(CString const& section, CString const& key, unsigned long defaultValue)
{
CString strValue = GetString(section, key);
if(strValue.IsEmpty())
return defaultValue;
unsigned long value(defaultValue);
try
{
int base(10);
char* pBuffer = strValue.GetBuffer(strValue.GetLength());
char* pBufferEnd = &pBuffer[strValue.GetLength()-1];
value = strtoul(pBufferEnd, &pBufferEnd,base);
strValue.ReleaseBuffer(strValue.GetLength());
}
catch (CException* e)
{
UNUSED_ALWAYS(e);
strValue.ReleaseBuffer(strValue.GetLength());
return value;
}
return value;
}
void CCustomIniFile::SetUnsignedLong(CString const& section, CString const& key, unsigned long value)
{
CString strValue;
strValue.Format("%d", value);
SetString(section, key, strValue);
}
byte CCustomIniFile::GetByte(CString const& section, CString const& key, byte defaultValue)
{
return (byte)GetInt(section, key, defaultValue);
}
void CCustomIniFile::SetByte(CString const& section, CString const& key, byte value)
{
SetInt(section, key, value);
}
bool CCustomIniFile::GetBool(CString const& section, CString const& key, bool defaultValue)
{
if(GetInt(section, key, defaultValue))
return true;
return false;
}
void CCustomIniFile::SetBool(CString const& section, CString const& key, bool value)
{
SetInt(section, key, value);
}
float CCustomIniFile::GetFloat(CString const& section, CString const& key, float defaultValue)
{
return (float)GetDouble(section, key, defaultValue);
}
void CCustomIniFile::SetFloat(CString const& section, CString const& key, float value)
{
CString strValue;
strValue.Format("%f", value);
SetString(section, key, strValue);
}
double CCustomIniFile::GetDouble(CString const& section, CString const& key, double defaultValue)
{
CString strValue = GetString(section, key);
if(strValue.IsEmpty())
return defaultValue;
int value(defaultValue);
try
{
value = atof(strValue.GetBuffer(strValue.GetLength()));
strValue.ReleaseBuffer(strValue.GetLength());
}
catch (CException* e)
{
UNUSED_ALWAYS(e);
strValue.ReleaseBuffer(strValue.GetLength());
return value;
}
return value;
}
void CCustomIniFile::SetDouble(CString const& section, CString const& key, double value)
{
CString strValue;
strValue.Format("%f", value);
SetString(section, key, strValue);
}
CTime CCustomIniFile::GetDateTime(CString const& section, CString const& key, CTime defaultValue)
{
//兼容-1-2 10:2:3,2005-01-02 10:02:03两种格式
//也可以只有日期没有时间,如-01-02或2005-1-2
CString strValue = GetString(section, key);
if(strValue.IsEmpty())
return defaultValue;
strValue.TrimLeft();
strValue.TrimRight();
try
{
//year
int monthPos = strValue.Find('-');
if(monthPos == -1)
return defaultValue;
int nYear = atoi(strValue.Mid(0,monthPos));
//month
int dayPos = strValue.Find('-',monthPos+1);
if(dayPos == -1)
return defaultValue;
int nMonth = atoi(strValue.Mid(monthPos+1,dayPos - monthPos -1));
//day
int hPos = strValue.Find(' ',dayPos +1);
if(hPos == -1)
return defaultValue;
int nDay = atoi(strValue.Mid(dayPos+1,hPos - dayPos -1));
//hour
int mPos = strValue.Find(':',hPos +1 );
if(mPos == -1)
return CTime(nYear, nMonth, nDay,0, 0, 0);
int nHour = atoi(strValue.Mid(hPos+1,mPos-hPos -1));
//minute
int sPos = strValue.Find(':',mPos+1);
if(sPos== -1)
return CTime(nYear, nMonth, nDay,0, 0, 0);
int nMinute = atoi(strValue.Mid(mPos+1,sPos - mPos -1));
//second
int nSecond = atoi(strValue.Mid(sPos+1,strValue.GetLength() - sPos -1));
return CTime(nYear,nMonth,nDay,nHour,nMinute,nSecond);
}
catch (CException* e)
{
UNUSED_ALWAYS(e);
return defaultValue;
}
}
void CCustomIniFile::SetDateTime(CString const& section, CString const& key, CTime value)
{
CString strValue = value.Format(_T("%Y-%m-%d %H:%M:%S"));
SetString(section, key, strValue);
}
CTime CCustomIniFile::GetDate(CString const& section, CString const& key, CTime defaultValue)
{
return GetDateTime(section, key, defaultValue);
}
void CCustomIniFile::SetDate(CString const& section, CString const& key, CTime value)
{
CString strValue = value.Format(_T("%Y-%m-%d"));
SetString(section, key, strValue);
}
CTime CCustomIniFile::GetTime(CString const& section, CString const& key, CTime defaultValue)
{
//兼容:2:3,10:02:03两种格式
CString strValue = GetString(section, key);
if(strValue.IsEmpty())
return defaultValue;
strValue.TrimLeft();
strValue.TrimRight();
try
{
//hour
int hPos = 0;
int mPos = strValue.Find(':');
if(mPos == -1)
return defaultValue;
int nHour = atoi(strValue.Mid(hPos+1,mPos-hPos -1));
//minute
int sPos = strValue.Find(':',mPos+1);
if(sPos== -1)
return defaultValue;
int nMinute = atoi(strValue.Mid(mPos+1,sPos - mPos -1));
//second
int nSecond = atoi(strValue.Mid(sPos+1,strValue.GetLength() - sPos -1));
return CTime(1980, 1, 1, nHour,nMinute,nSecond);
}
catch (CException* e)
{
UNUSED_ALWAYS(e);
return defaultValue;
}
}
void CCustomIniFile::SetTime(CString const& section, CString const& key, CTime value)
{
CString strValue = value.Format(_T("%H:%M:%S"));
SetString(section, key, strValue);
}
BOOL CCustomIniFile::SectionExists(CString const& section)
{
std::vector<CString> sectionList = GetSections();
for (std::vector<CString>::iterator it = sectionList.begin(); it!= sectionList.end(); ++it)
{
if(section == *it)
return TRUE;
}
return FALSE;
}
BOOL CCustomIniFile::KeyExists(CString const& section, CString const& key)
{
std::vector<CString> keyList = GetKeys(section);
for (std::vector<CString>::iterator it = keyList.begin(); it!= keyList.end(); ++it)
{
if(key == *it)
return TRUE;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////////
//CIniFile
/////////////////////////////////////////////////////////////////////////////////
#define BUFFER_SIZE 65536
char buffer[BUFFER_SIZE];
CIniFile::CIniFile(CString const& fileName):CCustomIniFile(fileName)
{
SetFileName(fileName);
}
CIniFile::~CIniFile()
{
}
CString CIniFile::GetString(CString const& section, CString const& key, CString const& defaultValue)
{
//如果键值是用引号括起来的,则返回值中将不包含引号
//比如key = "value"
//或 key = 'value'
//则返回值将是value
memset(buffer,0,BUFFER_SIZE);
int size = GetPrivateProfileStringA(section, key, defaultValue, buffer, BUFFER_SIZE, m_fileName);
return buffer;
}
void CIniFile::SetString(CString const& section, CString const& key, CString const& value)
{
//对于两头含有空格的值,如果不用引号括起来,
//则在读取的时候,这些空格会被自动去掉
int strLen = value.GetLength();
CString tempValue(value);
if( strLen > 0 && (value.GetAt(0) == ' ' || value.GetAt(value.GetLength()-1) == ' '))
tempValue.Format("""%s""", value);
WritePrivateProfileStringA(section, key, tempValue, m_fileName);
}
void CIniFile::DeleteKey(CString const& section, CString const& key)
{
WritePrivateProfileStringA(section, key,NULL,m_fileName);
}
void CIniFile::DeleteSection(CString const& section)
{
WritePrivateProfileSectionA(section,NULL,m_fileName);
}
void CIniFile::AddSection(CString section)
{
WritePrivateProfileSectionA(section, "", m_fileName);
}
std::vector<CString> CIniFile::GetSections()
{
memset(buffer, 0, BUFFER_SIZE);
int size = GetPrivateProfileSectionNamesA(buffer,BUFFER_SIZE,m_fileName);
return BufferToStringList(buffer, size);
}
std::vector<CString> CIniFile::GetKeys(CString const& section)
{
memset(buffer, 0, BUFFER_SIZE);
int size = GetPrivateProfileStringA(section, NULL, NULL, buffer, BUFFER_SIZE, m_fileName);
return BufferToStringList(buffer, size);
}
std::vector<CString> CIniFile::GetSectionValues(CString const& section)
{
//该类只能这么实现
return GetKeys(section);
}
void CIniFile::UpdateFile()
{
//此处参考了delphi版的TIniFile的实现
WritePrivateProfileStringA(NULL, NULL, NULL, m_fileName);
}
std::vector<CString> CIniFile::BufferToStringList(char* buf, int size)
{
int iCnt, iPos;
std::vector<CString> strList;
CString sectionName;
if (size>0)
{
iCnt = 0; iPos = 0;
for (iCnt = 0; iCnt < size; iCnt++)
{
if (buf[iCnt] == 0x00)
{
char nameBuf[1000];
memset(nameBuf,0,1000);
memcpy(nameBuf, &buf[iPos],iCnt - iPos);
sectionName = nameBuf;
iPos = iCnt + 1;
if(!sectionName.IsEmpty())
strList.push_back(sectionName);
}
}
}
return strList;
}
/////////////////////////////////////////////////////////////////////////////////
//CMemIniFile
/////////////////////////////////////////////////////////////////////////////////
CMemIniFile::CMemIniFile(CString const& fileName, bool bCaseSensitive):CCustomIniFile(fileName),m_bCaseSensitive(bCaseSensitive)
{
SetFileName(fileName);
}
CMemIniFile::~CMemIniFile()
{
}
void CMemIniFile::Reset()
{
CCustomIniFile::Reset();
m_fileContent.clear();
m_sectionIndex.clear();
m_sectionKeyIndex.clear();
}
void CMemIniFile::SetFileName(CString const& fileName)
{
CCustomIniFile::SetFileName(fileName);
m_fileContent.clear();
m_sectionIndex.clear();
m_sectionKeyIndex.clear();
ReadfileContent();
GenerateIndex();
}
void CMemIniFile::GenerateIndex()
{
m_sectionIndex.clear();
m_sectionKeyIndex.clear();
m_sectionLineNumSet.clear();
try
{
int i = 0;
CString currentSection;
for (CFileContent::iterator it = m_fileContent.begin(); it != m_fileContent.end(); ++it,++i)
{
CString& oneLine = *it;
//生成section索引
if(oneLine.Left(1) == "[" && oneLine.Right(1) == "]")
{
currentSection = oneLine.Mid(1, oneLine.GetLength() - 2);
currentSection.TrimLeft();
currentSection.TrimRight();
m_sectionIndex[currentSection] = i;
}
else
{//生成key的索引
int index = oneLine.Find('=', 1); //不允许键为空
if(index > 0)
{
CString key = oneLine.Left(index);
key.TrimRight();
m_sectionKeyIndex[currentSection][key] = i;
}
}
}
//生成section的行号列表
for (CSectionIndex::iterator it2 = m_sectionIndex.begin(); it2 != m_sectionIndex.end(); ++it2)
m_sectionLineNumSet.insert( (*it2).second);
}
catch (...)
{
m_sectionIndex.clear();
m_sectionKeyIndex.clear();
m_sectionLineNumSet.clear();
return;
}
}
void CMemIniFile::ReadfileContent()
{
if(m_fileName.IsEmpty())
return;
m_fileContent.clear();
CStdioFile file;
try
{
file.Open(m_fileName, CFile::modeRead, NULL);
CString oneLine;
while (file.ReadString(oneLine))
{
oneLine.TrimLeft();
oneLine.TrimRight();
//不允许空行
if(oneLine.IsEmpty())
continue;
m_fileContent.push_back(oneLine);
}
}
catch (...)
{
m_sectionIndex.clear();
m_fileContent.clear();
m_sectionLineNumSet.clear();
return;
}
}
CString CMemIniFile::GetString(CString const& section, CString const& key, CString const& defaultValue)
{
//查找section的索引
CSectionKeyIndex::iterator sectionPos;
if(m_bCaseSensitive)
sectionPos = m_sectionKeyIndex.find(section);
else
sectionPos = std::find_if(m_sectionKeyIndex.begin(), m_sectionKeyIndex.end(), compare_nocase(section));
if(sectionPos == m_sectionKeyIndex.end())
return "";
//查找key的索引
CSectionIndex& keyIndex = (*sectionPos).second;
CSectionIndex::iterator keyPos;
if(m_bCaseSensitive)
keyPos = keyIndex.find(key);
else
keyPos = std::find_if(keyIndex.begin(), keyIndex.end(), compare_nocase(key));
if(keyPos == keyIndex.end())
return "";
//获取键值
CString& oneLine = m_fileContent[(*keyPos).second];
int index = oneLine.Find('=');
if(index <= 0)
return "";
++index;
return oneLine.Mid(index, oneLine.GetLength() - index);
}
void CMemIniFile::SetString(CString const& section, CString const& key, CString const& value)
{
//获取secion的索引
CSectionKeyIndex::iterator sectionPos;
if(m_bCaseSensitive)
sectionPos = m_sectionKeyIndex.find(section);
else
sectionPos = std::find_if(m_sectionKeyIndex.begin(), m_sectionKeyIndex.end(), compare_nocase(section));
//针对section不存在的情况
if(sectionPos == m_sectionKeyIndex.end())
{
//添加一个section和key
CString oneLine;
oneLine.Format("[%s]", section);
m_fileContent.push_back(oneLine);
oneLine.Format("%s=%s", key, value);
m_fileContent.push_back(oneLine);
GenerateIndex();
return;
}
//获取key的索引
CSectionIndex& keyIndex = (*sectionPos).second;
CSectionIndex::iterator keyPos;
if(m_bCaseSensitive)
keyPos = keyIndex.find(key);
else
keyPos = std::find_if(keyIndex.begin(), keyIndex.end(), compare_nocase(key));
//针对key不存在的情况
if(keyPos == (*sectionPos).second.end())
{
//添加一个key
CFileContent::iterator filePos = m_fileContent.begin();
std::advance(filePos, m_sectionIndex[section] + 1);
CString oneLine;
oneLine.Format("%s=%s", key, value);
m_fileContent.insert(filePos, oneLine);
GenerateIndex();
return;
}
//修改
if((*keyPos).second < m_fileContent.size())
m_fileContent[ (*keyPos).second].Format("%s=%s", key, value);
}
void CMemIniFile::DeleteKey(CString const& section, CString const& key)
{
//获取section的索引
CSectionKeyIndex::iterator sectionPos;
if(m_bCaseSensitive)
sectionPos = m_sectionKeyIndex.find(section);
else
sectionPos = std::find_if(m_sectionKeyIndex.begin(), m_sectionKeyIndex.end(), compare_nocase(section));
if(sectionPos == m_sectionKeyIndex.end())
return;
//获取key的索引
CSectionIndex& keyIndex = (*sectionPos).second;
CSectionIndex::iterator keyPos;
if(m_bCaseSensitive)
keyPos = keyIndex.find(key);
else
keyPos = std::find_if(keyIndex.begin(), keyIndex.end(), compare_nocase(key));
if(keyPos == keyIndex.end())
return;
//删除
CFileContent::iterator filePos = m_fileContent.begin();
std::advance(filePos, (*keyPos).second);
m_fileContent.erase(filePos);
//重新生成索引
GenerateIndex();
}
void CMemIniFile::DeleteSection(CString const& section)
{
//获取section的索引
CSectionIndex::iterator sectionPos;
if(m_bCaseSensitive)
sectionPos = m_sectionIndex.find(section);
else
sectionPos = std::find_if(m_sectionIndex.begin(), m_sectionIndex.end(), compare_nocase(section));
if(sectionPos == m_sectionIndex.end())
return;
//获取下一个section的索引
int firstSectionOffset = (*sectionPos).second;
int secondSectionOffset = m_fileContent.size();
CSectionLineNumSet::iterator lineNumPos = m_sectionLineNumSet.find(firstSectionOffset);
if(lineNumPos == m_sectionLineNumSet.end())
return;
//查找下一个section的起始位置
++lineNumPos;
if(lineNumPos != m_sectionLineNumSet.end())
secondSectionOffset = (*lineNumPos);
CFileContent::iterator beginPos = m_fileContent.begin();
CFileContent::iterator endPos = m_fileContent.begin();
std::advance(beginPos, firstSectionOffset);
std::advance(endPos, secondSectionOffset);
//删除两个索引之间的内容
m_fileContent.erase(beginPos, endPos);
//重新生成索引
GenerateIndex();
}
void CMemIniFile::AddSection(CString section)
{
//添加一个section
CString oneLine;
oneLine.Format("[%s]", section);
m_fileContent.push_back(oneLine);
//重新生成索引
GenerateIndex();
}
std::vector<CString> CMemIniFile::GetSections()
{
std::vector<CString> result;
for (CSectionIndex::iterator it = m_sectionIndex.begin(); it != m_sectionIndex.end(); ++it)
{
result.push_back((*it).first);
}
return result;
}
std::vector<CString> CMemIniFile::GetKeys(CString const& section)
{
//获取section的索引
std::vector<CString> result;
CSectionKeyIndex::iterator sectionPos;
if(m_bCaseSensitive)
sectionPos = m_sectionKeyIndex.find(section);
else
sectionPos = std::find_if(m_sectionKeyIndex.begin(), m_sectionKeyIndex.end(), compare_nocase(section));
if(sectionPos == m_sectionKeyIndex.end())
return result;
//从key的索引表内获取key列表
CSectionIndex& keyIndexs = (*sectionPos).second;
for (CSectionIndex::iterator it = keyIndexs.begin(); it != keyIndexs.end(); ++it)
result.push_back( (*it).first);
return result;
}
std::vector<CString> CMemIniFile::GetSectionValues(CString const& section)
{
std::vector<CString> result;
//获取section的索引
CSectionIndex::iterator sectionPos;
if(m_bCaseSensitive)
sectionPos = m_sectionIndex.find(section);
else
sectionPos = std::find_if(m_sectionIndex.begin(), m_sectionIndex.end(), compare_nocase(section));
if(sectionPos == m_sectionIndex.end())
return result;
//获取下一个section的索引
int firstSectionOffset = (*sectionPos).second;
int secondSectionOffset = m_fileContent.size();
CSectionLineNumSet::iterator lineNumPos = m_sectionLineNumSet.find(firstSectionOffset);
if(lineNumPos == m_sectionLineNumSet.end())
return result;
//查找下一个section的起始位置
++lineNumPos;
if(lineNumPos != m_sectionLineNumSet.end())
secondSectionOffset = (*lineNumPos);
CFileContent::iterator beginPos = m_fileContent.begin();
CFileContent::iterator endPos = m_fileContent.begin();
std::advance(beginPos, firstSectionOffset);
//不能包含section头本身
++beginPos;
std::advance(endPos, secondSectionOffset);
for ( ;beginPos != endPos; ++beginPos)
result.push_back(*beginPos);
return result;
}
void CMemIniFile::UpdateFile()
{
if(m_fileName.IsEmpty())
return;
CStdioFile file;
try
{
CCustomIniFile::Reset();
file.Open(m_fileName, CFile::modeWrite, NULL);
for (CFileContent::iterator it = m_fileContent.begin(); it != m_fileContent.end(); ++it)
{
file.WriteString(*it + ""r"n");
}
file.Close();
}
catch (...)
{
m_sectionIndex.clear();
m_fileContent.clear();
m_sectionLineNumSet.clear();
return;
}
}