使WINCE支持INI配置文件
在我们编写的应用软件中,某些情况下不可避免的会使用一些配置文件来提高我们的应用程序的灵活性。Wince中不支持INI文件的读取。
我封装了一个类来读取INI文件,其中主要实现了一下几个功能:
//读取值
BOOL GetValueString(const PCHAR pSection, const PCHAR pKey, PCHAR pReturnValue);
BOOL GetValueInteger(const PCHAR pSection, const PCHAR pKey, PDWORD pdwReturnValue);
//写入值
BOOL SetValueString(const PCHAR pSection, const PCHAR pKey, const PCHAR pSetValue, BOOL bNeedCreate);
BOOL SetValueInteger(const PCHAR pSection, const PCHAR pKey, PDWORD pdwSetValue, BOOL bNeedCreate);
目前还没有实现SET功能,但是一般的配置文件的读取已经实现,我是一个新程序员,使用的方法也比较笨。
下面是我的大概思路:首先,我们不知道一个INI配置文件到底有多大,对于嵌入式系统,内存空间是有限的,虽然现在基本都是64M以上了,但是我们也不能过多的使用内存,应当合理利用。打开文件之后,读取其中的内容到内存中,每次只读取一个块。
读取的块由get功能里面的pSection决定,首先查找文件中的字符,将相应的块读取到内存中,然后再由pKey来查找需要的值。
代码如下:查找块名是读取一行之后比较
1. 读取每一行
BOOL CIniFileOP::ReadOneLine(PCHAR OutBuffer)
{
DWORD total, i = 0, j = 1, FilePointer=0;
CHAR temp[MAXINLINE] = {0};
while (1)
{
i = 0;
while(1)
{
ReadFile(m_fileHandle, &temp[i], 1, &total, NULL);
if (0 == total)
{
RETAILMSG(DBGMSGON, (_T("End-of-file\r\n")));
return FALSE;
}
FilePointer++;
lFilePointer = FilePointer;
if (0x0d == temp[i]) // \n,enter
{
temp[i] = '\0';
}
if (0x0a == temp[i]) // \r,newline
{
break;
}
i++;
}
temp[i] = '\0';
#if DBGMSGON
TCHAR wTemp[MAXINLINE];
mbstowcs(wTemp, temp, sizeof(temp));
RETAILMSG(DBGMSGON, (_T("::%d::\t"), j));
RETAILMSG(DBGMSGON, (wTemp));
RETAILMSG(DBGMSGON, (_T("\r\n")));
#endif
if (DeleteSpaceL(temp))
{
if (';' != temp[0] || '#' != temp[0])
{
DeleteNote(temp);
DeleteSpaceR(temp);
memcpy(OutBuffer, temp, sizeof(temp));
return TRUE;
}
}
j++;
}
return FALSE;
}
2. 在读取完成之后删除前后的空格!这个里面是没有任何比较在里面的,然后我们需要写一个读取一个块的函数。
BOOL CIniFileOP::ReadOneSection(const PCHAR pSection)
{
CHAR Temp[MAXINLINE] = {0}, Temp2[MAXINLINE] = {0};
DWORD KeyNum = 0;
if (INVALID_HANDLE_VALUE == m_fileHandle)
{
IniFileErrorHandle(_T("<>OPEN FAILED!!\r\n"));
return FALSE;
}
strcpy(SectionNameOpened, pSection);
memset(OneSection, 0, sizeof(OneSection));
SetFilePointer (m_fileHandle, 0, NULL, FILE_BEGIN);
while (ReadOneLine(Temp2))
{
if ('[' == Temp2[0])
{
for (INT i = 1, j = 0; ']' != Temp2[i]; i++, j++)
{
if (' ' != Temp2[i])
{
Temp[j] = Temp2[i];
}
else
{
i++;
}
}
Temp[j] = '\0';
}
memset(Temp2, 0, sizeof(Temp2));
if (strcmp(Temp,pSection)==0)
{
memset(Temp, 0, sizeof(Temp));
while (ReadOneLine(Temp))
{
if ('[' != Temp[0])
{
strcpy(OneSection[KeyNum], Temp);
//OneSection[KeyNum] = Temp;
KeyNum++;
}
else
{
if (0 == KeyNum)
{
RETAILMSG(DBGMSGON, (_T("This section have no key\r\n")));
return FALSE;
break;
}
dwKeyNum_OpenedSection = KeyNum;
return TRUE;
break;
}
}
}
}
RETAILMSG(DBGMSGON, (_T("You want section is not exist!!!\r\n")));
return FALSE;
}
在这个类里面,读取一个块之后,将这个块的名字记录下来,以便下一次查找,如果下一次查找的KEY值仍然是这个块里面的,哪么我们就无需再读取了
3.
BOOL CIniFileOP::GetValueString(const PCHAR pSection, const PCHAR pKey, PCHAR pReturnValue)
{
CHAR TempValue[MAXINLINE] = {0}, TempKey[MAXINLINE] = {0};
INT i = 0;
if (0 != strcmp(pSection, SectionNameOpened))
{
ReadOneSection(pSection);
}
if (0 == dwKeyNum_OpenedSection)
{
RETAILMSG(DBGMSGON,(_T("This section have no key\r\n")));
}
for (DWORD j = 0; j < dwKeyNum_OpenedSection; j++)
{
memset(TempKey, 0, sizeof(TempKey));
for (INT i = 0; '=' != OneSection[j][i]; i++)
{
TempKey[i] = OneSection[j][i];
}
if (0 == strcmp(pKey, TempKey))
{
if ('=' == OneSection[j][i])
{
i++;
}
for (INT k = 0; '\0' != OneSection[j][i]; k++)
{
TempValue[k] = OneSection[j][i];
i++;
}
TempValue[k] = '\0';
strcpy(pReturnValue, TempValue);
RETAILMSG(DBGMSGON, (_T("Find the key\r\n")));
return TRUE;
}
}
RETAILMSG(DBGMSGON, (_T("Not found you key in this section!!\r\n")));
return FALSE;
}
就这么几个简单的函数就可以实现wince下ini文件的操作,淡然其中省略了一些我们常用的函数,比如删除前后空格或者是删除前后回车换行等。
3. GetValueInteger的实现方法就比较简单了,我们用字符型把值读出来,然后再转换呢成整形,这样就可以实现了
其实总体来说,我用的方法比较复杂,而且效率不是很高,我非常愿意和有兴趣的人一起讨论,希望能够改善我的代码!让他尽可能少的出现BUG或者低效率情况!