VC版的IniFile

 

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;

    }  

}

原文地址:https://www.cnblogs.com/strinkbug/p/1357801.html