前言:
相信很多朋 友在編寫自己的程序中,都需要把一些數據先期導入到程序中進行初始化。那麼這個時候,比較好的做法就是把你所有的數據寫入一個ini文件,然後在程序去讀ini文件中的數據對行初始化。
一.INI簡介
那麼什麼是ini文件呢?ini文件是Initialization file的縮寫,意即初始化文件。(從名字就可以看出它的功能了吧)。不僅你自己的程序可以使用ini文件,其實windows操作系統也有自己的ini文件---win.ini,保存在%WinDir%\system32目錄下。Windows通過該文件對當前操作系統進行配置。
ini文件裏的數據的存取是採取的是預先約定好的 “項-值”存儲結構,各種數據被分門別類的存儲。以下是win.ini 文件的部分內容。
通過以上內容,我們可以看到,ini文件將各種數據分成很多以“[ ]”組成的節,而在每一個“節”中又包含了很多“項”,“項”後面緊跟着一個等號,等號後面則是該項的值。在該例中[Mail]就是一個“節”,MAPI是一個項,1則是MAPI的值。
所以,它的通用形式我們可以總結成:
[Section]
Key=KeyValue
二.操作ini文件的API
windows SDK提供有兩組API對ini文件進行讀寫。
對用戶的配置文件來說,一般我們使用的是表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<</span>MAX_ALLSECTIONS; i++)
{
if( chAllSections[i] == NULL )
{
if( chAllSections[i] == chAllSections[i+1] )
break;
}
}
i++; // 保證數據讀完
strArrSection.RemoveAll(); // 清空數組
for(j=0; j<</span>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<</span>MAX_ALLSECTIONS; i++)
{
if( chAllKeysAndValues[i] == NULL )
{
if( chAllKeysAndValues[i] == chAllKeysAndValues[i+1] )
break;
}
}
i++;
strArrKey.RemoveAll();
strArrKeyValue.RemoveAll();
for(j=0; j<</span>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<</span>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<</span>num; i++)
{
str += arrSection[i] + " ";//str="student computer ";
}
//得到所有Key和KeyValue
int num = file.GetAllKeysAndValues("computer", arrKey, arrkeyValue);
str = "";
for(int j=0; j<</span>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而不是字符串