大家都应该知道读取配置文件可以使用系统api GetPrivateProfileString ()(函数原型如下),我原先也对其打包成了一个类,但是今天要使用的时候,竟然出问题了(以前没有出过错的),试了几次还是没有什么效果,一气之下自己动手写了一个。
DWORD GetPrivateProfileString(
LPCTSTR lpAppName,
LPCTSTR lpKeyName,
LPCTSTR lpDefault,
LPTSTR lpReturnedString,
DWORD nSize,
LPCTSTR lpFileName
)
呵呵,无聊的人嘛。其中考虑到的因素有:
1. 有人喜欢写 key=value,而有人喜欢key = value,中间空格情况必须要处理。
2. 有的配置文件中,每个section之间加上一个空行,这不能不考虑。
3. 为了增快速度,我减少了读取文件次数,本来是想,每读取一个键的时候,记录键及其键值的,但是测试结果表明,不如一次读取的快(牺牲空间来达到性能--很常规的做法)
代码贴在下面,测试通过:
/******************************************************************************
PrivateProfile.h
Written by DS
in 09.03.2005
This class is used to simplified read the profiles
******************************************************************************/
#ifndef DARKSTAR_INITIALIZE_FILE_H
#define DARKSTAR_INITIALIZE_FILE_H
#include "afxcoll.h"
#include "afxtempl.h"
#include "Afx.h"
class CPrivateProfile
{
public:
CPrivateProfile (void);
~CPrivateProfile (void);
CPrivateProfile (LPCTSTR file);
int SetProfile (LPCTSTR file);
int GetInt (LPCTSTR section, LPCTSTR key, int nDefault = -1);
CString GetString (LPCTSTR section, LPCTSTR key, CString const& strDefault = "");
void GetAllKeys ();
//void GetAllKeys (CMapStringToString& map);
void GetSectionKeys (LPCTSTR section);
//void GetSectionKeys (LPCTSTR section, CMapStringToString& map);
int GetTotalKeys ();
protected:
CFile proFile;
CList <CString> sections;
CMapStringToString keyMap;
bool bInit;
};
#endif //DARKSTAR_INITIALIZE_FILE_H
//PrivateProfile.cpp
#include "StdAfx.h"
#include "PrivateProfile.h"
#include <iostream>
using namespace std;
CPrivateProfile::CPrivateProfile(void)
{
bInit = false;
keyMap.RemoveAll ();
}
CPrivateProfile::~CPrivateProfile(void)
{
proFile.Close ();
keyMap.RemoveAll ();
}
CPrivateProfile::CPrivateProfile (LPCTSTR file)
{
if (!proFile.Open (file, CFile::modeReadWrite))
exit (-1);
keyMap.RemoveAll ();
}
int CPrivateProfile::SetProfile (LPCTSTR file)
{
if (!proFile.Open (file, CFile::modeReadWrite))
return -1;
keyMap.RemoveAll ();
GetAllKeys ();
return 0;
}
void CPrivateProfile::GetAllKeys ()
{
proFile.SeekToBegin ();
int size = 2048;
char* buf;
int len;
//Read all context of the file into the memory
while (true) {
proFile.SeekToBegin ();
buf = new char[size];
memset (buf, 0, size);
len = proFile.Read (buf, size);
if (len + 1 < size) {//reach to end of file
break;
}
delete[] buf;
size *= 2;
}
if (buf[len - 1] != '/n')
buf[len] = '/n';
int pos = 0;
int offset = 0;
CString section;
CString key;
CString value;
while (buf[pos] != 0) {
if (buf[offset] == '/n') { //Null line
cout << "NULL line offset = " << offset << endl;
pos++;
offset = pos;
continue;
}
if (buf[pos] != '/n') {//now line terminator
pos++;
continue;
}
//line
CString line (buf + offset, pos - offset);
//cout << "buf[offset]:" << buf[offset];
if (pos < len);
pos++;
offset = pos;
//cout << "Deal with line :" << (LPCTSTR) line << endl;
line.Trim ();
//cout << "After Trim () :" << (LPCTSTR) line << endl;
//If this line
if (line[0] == '[' && line[line.GetLength () - 1] == ']') {
section = line.Mid (1, line.GetLength () - 2);
sections.AddTail (section);
//cout << "Section : " << (LPCTSTR) section << endl;
continue;
}
int tpos = line.Find ('=');
if (-1 == tpos || 0 == tpos || line.GetLength () - 1 == tpos) { //invalid position of '='
continue;
}
key = section;
key += "-";
key += line.Left (tpos);
key.Trim ();
value = line.Right (line.GetLength () - tpos - 1);
value.Trim ();
//cout << "Key : " << (LPCTSTR)key << "-> Value : " << (LPCTSTR)value << endl;
keyMap.SetAt (key, value);
}
bInit = true;
}
void CPrivateProfile::GetSectionKeys (LPCTSTR section)
{
proFile.SeekToBegin ();
int size = 2048;
char* buf;
int len;
//Read all context of the file into the memory
while (true) {
proFile.SeekToBegin ();
buf = new char[size];
memset (buf, 0, size);
len = proFile.Read (buf, size);
if (len < size) {//reach to end of file
break;
}
delete[] buf;
size *= 2;
}
char* des = new char[strlen (section) + 3];
sprintf (des, "[%s]", section);
char* p = strstr (buf, des);
if (NULL == p)
return ;
p = strchr (p, '/n');
int pos = p - buf + 1;
int offset = pos;
CString key;
CString value;
while (buf[pos] != 0) {
if (buf[pos] == '[') //stop, when ge to the next section
break;
if (buf[pos] != '/n') {//now line terminator
pos++;
continue;
}
if (pos == offset) { //Null line
offset++;
pos++;
continue;
}
//line
CString line (buf + offset, pos - offset);
pos++;
offset = pos;
line.Trim ();
int tpos = line.Find ('=');
if (-1 == tpos || 0 == tpos || line.GetLength () - 1 == tpos) { //invalid position of '='
continue;
}
key = section;
key += "-";
key += line.Left (tpos);
value = line.Right (line.GetLength () - tpos - 1);
keyMap.SetAt (key, value);
}
}
CString CPrivateProfile::GetString (LPCTSTR section, LPCTSTR key, CString const& strDefault)
{
if (!bInit)
GetAllKeys ();
CString s = section;
s += '-';
s += key;
CString value;
if (keyMap.Lookup (s, value))
return value;
return strDefault;
}
int CPrivateProfile::GetInt (LPCTSTR section, LPCTSTR key, int nDefault)
{
if (!bInit)
GetAllKeys ();
CString s = section;
s += '-';
s += key;
CString value;
if (keyMap.Lookup (s, value))
return atoi ((LPCTSTR) value);
return nDefault;
}
int CPrivateProfile::GetTotalKeys ()
{
if (!bInit)
GetAllKeys ();
return keyMap.GetSize ();
}
测试的主函数被我改了n次,基本上就是测试各种情况,没什么值得贴上来的东西。