天天看點

輕松實作一個操作ini檔案的類

前言:

    相信很多朋友在編寫自己的程式中,都需要把一些資料先期導入到程式中進行初始化。那麼這個時候,比較好的做法就是把你所有的資料寫入一個ini檔案,然後在程式去讀ini檔案中的資料對行初始化。

一.INI簡介

       那麼什麼是ini檔案呢?ini檔案是Initialization file的縮寫,意即初始化檔案。(從名字就可以看出它的功能了吧)。不僅你自己的程式可以使用ini檔案,其實windows作業系統也有自己的ini檔案---win.ini,儲存在%WinDir%/system32目錄下。Windows通過該檔案對目前作業系統進行配置。

    ini檔案裡的資料的存取是采取的是預先約定好的 “項-值”存儲結構,各種資料被分門别類的存儲。以下是win.ini 檔案的部分内容。

[Mail]

MAPI=1

CMC=1

CMCDLLNAME=mapi.dll

CMCDLLNAME32=mapi32.dll

MAPIX=1

MAPIXVER=1.0.0.1

OLEMessaging=1

                    表1

通過以上内容,我們可以看到,ini檔案将各種資料分成很多以“[ ]”組成的節,而在每一個“節”中又包含了很多“項”,“項”後面緊跟着一個等号,等号後面則是該項的值。在該例中[Mail]就是一個“節”,MAPI是一個項,1則是MAPI的值。

    是以,它的通用形式我們可以總結成:

[Section]

Key=KeyValue

二.操作ini檔案的API

windows SDK提供有兩組API對ini檔案進行讀寫。

GetPrivateProfileString

GetPrivateProfileInt

WritePrivateProfileString
GetPrivateProfileSection WritePrivateProfileSection
GetPrivateProfileSectionNames
GetPrivateProfileStruct WritePrivateProfileStruct

                                                                             表2

GetProfileString

GetProfileInt

WriteProfileString
GetProfileSection WritePrivateProfileSection

                                                                             表3

    對使用者的配置檔案來說,一般我們使用的是表2中的函數,這一點從函數中的“private”就可以看出它是針對私有的配置檔案的函數(又是廢話!)。而表3中的函數則是提供給針對系統配置檔案,即win.ini進行操作的函數。現隻準備介紹表2中的函數,這也是使用率最高的,表3中的函數操作和表2中的函數操作類同,故略。

DWORD GetPrivateProfileString(

  LPCTSTR lpAppName,           //節名,即Section

  LPCTSTR lpKeyName,           //項名,即Key

  LPCTSTR lpDefault,                //預設傳回字元串。如lpKeyName未找到,拷貝lpDefault到lpReturnedString

  LPTSTR lpReturnedString,       //傳回字元串的緩沖位址

  DWORD nSize,                       //緩沖大小

  LPCTSTR lpFileName             //ini檔案路徑

);

功能:根據指定的Section和 Key得到KeyValue,存放在lpReturnedString中

傳回:傳回拷貝到緩沖中的字元個數。不包括結束符

UINT GetPrivateProfileInt(

  LPCTSTR lpAppName,           //節名,即Section

  LPCTSTR lpKeyName,           //項名,即Key

  INT nDefault,                           //預設傳回整型值。如lpKeyName未找到,函數傳回nDefault的值

  LPCTSTR lpFileName             //ini檔案路徑

);

功能:根據指定的Section和 Key得到整型KeyValue

傳回:傳回得到的整型KeyValue

BOOL WritePrivateProfileString(

  LPCTSTR lpAppName,           //節名,即Section

  LPCTSTR lpKeyName,           //項名,即Key

  LPCTSTR lpString,                  //要寫入的字元串

  LPCTSTR lpFileName             //ini檔案路徑

);

功能:向指定的Section和 Key寫入KeyValue。

      如果lpString為NULL,則删除目前lpKeyName

    如果lpKeyName=lpString=NULL,則删除目前Section以及其下的所有Key

       如果Section或者Key不存在,則建立;存在則覆寫

DWORD GetPrivateProfileSectionNames(

  LPTSTR lpszReturnBuffer,             //存放所有Section的緩沖位址

  DWORD nSize,                             //緩沖大小

  LPCTSTR lpFileName                   //ini檔案路徑

);

功能:得到ini檔案中所有Section名。

傳回:傳回拷貝到緩沖中的字元個數。不包括結束符。

注意:傳回的所有Section在緩沖中的存放格式為“Section1”,0,“Section2”,0。。。。

      若需要得到具體的每個Section,則需要進行字元串解析。在後面的IniFile類中的GetAllKeysAndValues函數中會看到解

      析步驟。

DWORD GetPrivateProfileSection(

  LPCTSTR lpAppName,                   //節名,即Section   

  LPTSTR lpReturnedString,              //存放指定Section下所有的Key和KeyValue的緩沖位址

  DWORD nSize,                              //緩沖大小

  LPCTSTR lpFileName                     //ini檔案路徑

);

功能:得到指定Section下所有的Key和KeyValue。

傳回:傳回拷貝到緩沖中的字元個數。不包括結束符。

注意:傳回的“項-值對”在緩沖中的存放格式為“Key1=KeyValue1”,0,“Key2=KeyValue2”,0 。。。。

若需要得到具體的Key和KeyValue,則需要進行字元串解析。在後面的IniFile類中的GetAllKeysAndValues函數中會看到解析步驟。

GetPrivateProfileStruct和WritePrivateProfileStruct用的較少,本文也未介紹,感興趣的朋友可以自己看看MSDN,裡面也有詳細介紹。

三.一個ini的類

    有了以上的API後,我們就可以輕松的制作一個簡單的操作ini檔案的類了。

//

// File: IniFile.h

// Date: October 2004

// Author: lixiaosan

// Email: [email protected]

// Copyright (c) 2004. All Rights Reserved.

//

#if !defined(AFX_INIFILE_H__B5C0D7F7_8353_4C93_AAA4_38A688CA253C__INCLUDED_)

#define AFX_INIFILE_H__B5C0D7F7_8353_4C93_AAA4_38A688CA253C__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

class CIniFile 

{

public:

         CIniFile();

         virtual ~CIniFile();

         //    設定ini檔案路徑

    //    成功傳回TRUE;否則傳回FALSE

         BOOL         SetPath(CString strPath);

         //    檢查section是否存在

    //    存在傳回TRUE;否則傳回FALSE

         BOOL         SectionExist(CString strSection);

         //    從指定的Section和Key讀取KeyValue

        //    傳回KeyValue

         CString         GetKeyValue(CString    strSection,

                                                        CString    strKey);        

         //    設定Section、Key以及KeyValue,若Section或者Key不存在則建立

         void          SetKeyValue(CString    strSection,

                                                   CString    strKey,

                                                   CString    strKeyValue);

         //    删除指定Section下的一個Key

         void          DeleteKey(CString strSection,

                                               CString strKey);

         //    删除指定的Section以及其下的所有Key

         void          DeleteSection(CString strSection);

         //    獲得所有的Section

        //    傳回Section數目

         int              GetAllSections(CStringArray& strArrSection);

         //    根據指定Section得到其下的所有Key和KeyValue

        //    傳回Key的數目

         int              GetAllKeysAndValues(CString strSection,

                                                                     CStringArray& strArrKey,

                                                                     CStringArray& strArrKeyValue);

         //       删除所有Section

         void          DeleteAllSections();

private:

         //       ini檔案路徑

         CString m_strPath;

};

#endif // !defined(AFX_INIFILE_H__B5C0D7F7_8353_4C93_AAA4_38A688CA253C__INCLUDED_)

//

// File: IniFile.cpp

// Date: October 2004

// Author: lixiaosan

// Email: [email protected]

// Copyright (c) 2004. All Rights Reserved.

//

#include "stdafx.h"

//#include "test6.h"

#include "IniFile.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

#define         MAX_SECTION                260        //Section最大長度

#define         MAX_KEY                         260        //KeyValues最大長度

#define         MAX_ALLSECTIONS     65535    //所有Section的最大長度

#define         MAX_ALLKEYS              65535    //所有KeyValue的最大長度

//

// Construction/Destruction

//

CIniFile::CIniFile()

{

}

CIniFile::~CIniFile()

{

}

//

//   Public Functions

//

BOOL CIniFile::SetPath(CString strPath)

{

         m_strPath = strPath;

         //       檢查檔案是否存在

         DWORD  dwFlag = GetFileAttributes((LPCTSTR)m_strPath);

         //       檔案或者路徑不存在,傳回FALSE

         if( 0xFFFFFFFF == dwFlag )

                   return FALSE;

         //       路徑是目錄,傳回FALSE

         if (  FILE_ATTRIBUTE_DIRECTORY & dwFlag )

                   return FALSE;

         return TRUE;

}

BOOL CIniFile::SectionExist(CString strSection)

{

         TCHAR chSection[MAX_SECTION];

         DWORD dwRetValue;

         dwRetValue = GetPrivateProfileString(

                  (LPCTSTR)strSection,

                   NULL,

                   _T(""),

                  chSection,

                  sizeof(chSection)/sizeof(TCHAR),

                  (LPCTSTR)m_strPath);

         return (dwRetValue>0);

}

CString CIniFile::GetKeyValue(CString strSection,

                                                         CString strKey)

{

         TCHAR         chKey[MAX_KEY];

         DWORD         dwRetValue;

         CString strKeyValue=_T("");

         dwRetValue = GetPrivateProfileString(

                  (LPCTSTR)strSection,

                  (LPCTSTR)strKey,

                   _T(""),

                   chKey,

                  sizeof(chKey)/sizeof(TCHAR),

                  (LPCTSTR)m_strPath);      

         strKeyValue = chKey;

         return strKeyValue;

}

void CIniFile::SetKeyValue(CString strSection,

                                                 CString strKey,

                                                 CString strKeyValue)

{

         WritePrivateProfileString(

                  (LPCTSTR)strSection,

                  (LPCTSTR)strKey,

                  (LPCTSTR)strKeyValue,

                  (LPCTSTR)m_strPath);

}

void CIniFile::DeleteKey(CString strSection, CString strKey)

{

         WritePrivateProfileString(

                  (LPCTSTR)strSection,

                  (LPCTSTR)strKey,

                   NULL,          //       這裡寫NULL,則删除Key

                  (LPCTSTR)m_strPath);

}

void CIniFile::DeleteSection(CString strSection)

{

         WritePrivateProfileString(

                  (LPCTSTR)strSection,

                   NULL,         

                   NULL,          //       這裡都寫NULL,則删除Section

                  (LPCTSTR)m_strPath);

}

int CIniFile::GetAllSections(CStringArray& strArrSection)

{

         int dwRetValue, i, j, iPos=0;

         TCHAR chAllSections[MAX_ALLSECTIONS];

         TCHAR chTempSection[MAX_SECTION];

         ZeroMemory(chAllSections, MAX_ALLSECTIONS);

         ZeroMemory(chTempSection, MAX_SECTION);

         dwRetValue = GetPrivateProfileSectionNames(

                  chAllSections,

                  MAX_ALLSECTIONS,

                  m_strPath);

         //       因為Section在數組中的存放形式為“Section1”,0,“Section2”,0,0。

    //       是以如果檢測到連續兩個0,則break

         for(i=0; i<MAX_ALLSECTIONS; i++)

         {

                  if( chAllSections[i] == NULL )

                   {

                            if( chAllSections[i] == chAllSections[i+1] )

                                     break;

                   }

         }

         i++; //         保證資料讀完

         strArrSection.RemoveAll(); //         清空數組

         for(j=0; j<i; j++)

         {

                  chTempSection[iPos++] = chAllSections[j];

                  if( chAllSections[j] == NULL )

                   { 

                            strArrSection.Add(chTempSection);

                            ZeroMemory(chTempSection, MAX_SECTION);

                            iPos = 0;

                   }

         }

         return strArrSection.GetSize();

}

int CIniFile::GetAllKeysAndValues(CString  strSection,

                                                            CStringArray&         strArrKey,

                                                            CStringArray& strArrKeyValue)

{

         int dwRetValue, i, j, iPos=0;

         TCHAR chAllKeysAndValues[MAX_ALLKEYS];

         TCHAR chTempkeyAndValue[MAX_KEY];

         CString strTempKey;

         ZeroMemory(chAllKeysAndValues, MAX_ALLKEYS);

         ZeroMemory(chTempkeyAndValue, MAX_KEY);

         dwRetValue = GetPrivateProfileSection(

                  strSection,

                  chAllKeysAndValues,

                  MAX_ALLKEYS,

                  m_strPath);

         //       因為Section在數組中的存放形式為“Key1=KeyValue1”,0,“Key2=KeyValue2”,0

         //       是以如果檢測到連續兩個0,則break

         for(i=0; i<MAX_ALLSECTIONS; i++)

         {

                  if( chAllKeysAndValues[i] == NULL )

                   {

                            if( chAllKeysAndValues[i] == chAllKeysAndValues[i+1] )

                                     break;

                   }

         }

         i++;

         strArrKey.RemoveAll();

         strArrKeyValue.RemoveAll();

         for(j=0; j<i; j++)

         {

                  chTempkeyAndValue[iPos++] = chAllKeysAndValues[j];

                  if( chAllKeysAndValues[j] == NULL )

                   { 

                            strTempKey = chTempkeyAndValue;

                            strArrKey.Add( strTempKey.Left(strTempKey.Find('=')) );

                            strArrKeyValue.Add( strTempKey.Mid(strTempKey.Find('=')+1) );

                            ZeroMemory(chTempkeyAndValue, MAX_KEY);

                            iPos = 0;

                   }

         }

         return strArrKey.GetSize();

}

void CIniFile::DeleteAllSections()

{

         int nSecNum;

         CStringArray strArrSection;

         nSecNum = GetAllSections(strArrSection);

         for(int i=0; i<nSecNum; i++)

         {

                  WritePrivateProfileString(

                            (LPCTSTR)strArrSection[i],

                            NULL,

                            NULL,

                            (LPCTSTR)m_strPath);      

         }

}

四.例子

比如在存在一個myfile.ini檔案,内容如下:

[student]

number=40

male=25

female=15

average_age=15

[computer]

cpu=2.0

motherboard=ASUS

harddisk=120

ram=512

display=sansung

現在把IniFile.h和IniFile.cpp 加入到你的工程中。在使用他的類中#include “IniFile.h”;

         CIniFile file;

         CStringArray arrSection, arrKey, arrkeyValue;

         file.SetPath("f:// myfile.ini");

         CString str="";

         if(file.SectionExist("student"))

         {

                  //str="15"

                   str = file.GetKeyValue("student", "female");

                   //設定number為50

                  file.SetKeyValue("student", "number", "50");

                   //因為在student中computer_num不存在,是以增加一項

                  file.SetKeyValue("student", "computer_num", "30");

                   //得到所有section

                   int num = file.GetAllSections(arrSection);

                   str = "";

                   for(int i=0; i<num; i++)

                   {

                            str += arrSection[i] + " ";//str="student computer ";

                   }

                   //得到所有Key和KeyValue

                   int num = file.GetAllKeysAndValues("computer", arrKey, arrkeyValue);

                   str = "";

                   for(int j=0; j<num; j++)

                   {

                            //arrKey儲存了computer下所有的Key

                            //arrkeyValue儲存了computer下所有的KeyValue

                            str = arrKey[j];

                            str = arrkeyValue[j];

                   }

                   //删除student下的computer_num

                  file.DeleteKey("student", "computer_num");

                   //删除student

                  file.DeleteSection("student");

     }

    有興趣的朋友,可以在該類基礎上進行擴充,添加你自己喜歡的功能。比如說傳回int而不是字元串。

就講到這裡吧,歡迎大家指正。:) 

傳回:寫入成功。

    現在我們來看看這幾個函數的功能:

繼續閱讀