Date: 2012may16
OS: Windows
Language: C/C++
Keywords: GetPrivateProfileString, GetPrivateProfileSection
Q. Win32: Quickly read an ini file
A. Here is a small class for that.
IniFile.h
#include <windows.h>
#include <stdio.h>
#include <string>
#include <map>
typedef std::map<std::string, std::string, std::less<std::string> > INIFILE;
class IniFile
{
enum { MAXKEY = 5 * 1014 };
INIFILE inifile;
void chop(LPSTR);
void parseVarVal(LPSTR szLine, LPSTR *szVar, LPSTR *szVal);
void makeKey(LPSTR szKey, const size_t size, LPCSTR szSection, LPCSTR szVar)
{
_snprintf(szKey, size, "%s_%s", szSection, szVar);
}
public:
void put(LPCSTR szSection, LPCSTR szVar, LPCSTR szVal);
BOOL read(LPCSTR szFile);
std::string getStd(LPCSTR szSection, LPCSTR szVar);
BOOL getSz(LPCSTR szSection, LPCSTR szVar, LPSTR szVal, const size_t);
};
IniFile.cpp
#include "IniFile.h"
enum { MAXBUF = 5 * 1014 };
void IniFile::chop(LPSTR p)
{
for (; *p; p++)
{
if ((*p == '\r') || (*p == '\n'))
{
*p = '\0';
}
}
}
// WARNING: Klobbers input buffer
void IniFile::parseVarVal(LPSTR szLine, LPSTR *szVar, LPSTR *szVal)
{
char *p;
*szVar = *szVal = NULL;
if ((p = strchr(szLine, '=')) != NULL)
{
*szVar = szLine;
*p = '\0';
*szVal = p+1;
}
}
BOOL IniFile::read(LPCSTR szFile)
{
FILE *f;
char buf[MAXBUF];
char szSection[MAXBUF] = "";
LPSTR p;
LPSTR var, val;
if ((f = fopen(szFile, "rt")) == NULL)
{
perror("IniFile::read");
return FALSE;
}
for (;;)
{
if (fgets(buf, sizeof(buf), f) == NULL) break;
chop(buf);
if (buf[0] == '\0') continue;
if (buf[0] == '[')
{ // New section
if ((p = strrchr(buf, ']')) != NULL)
{
*p = '\0'; // Zap the closing square bracket
}
lstrcpyn(szSection, buf+1, sizeof(szSection));
}
else
{ // Regular line
parseVarVal(buf, &var, &val);
if (var == NULL || val == NULL) continue;
if (var[0] == '\0') continue;
put(szSection, var, val);
}
}
fclose(f);
return TRUE;
}
void IniFile::put(LPCSTR szSection, LPCSTR szVar, LPCSTR szVal)
{
char szKey[MAXKEY];
makeKey(szKey, sizeof(szKey), szSection, szVar);
inifile[szKey] = szVal;
}
// Get a value into a std::string
std::string IniFile::getStd(LPCSTR szSection, LPCSTR szVar)
{
char szKey[MAXKEY];
makeKey(szKey, sizeof(szKey), szSection, szVar);
return inifile[szKey];
}
// Get a value into a regular C string
BOOL IniFile::getSz(LPCSTR szSection, LPCSTR szVar, LPSTR szVal, const size_t size)
{
char szKey[MAXKEY];
INIFILE::const_iterator it;
szVal[0] = '\0';
makeKey(szKey, sizeof(szKey), szSection, szVar);
if ((it = inifile.find(szKey)) == inifile.end())
{
return FALSE;
}
lstrcpyn(szVal, (*it).second.c_str(), size);
return TRUE;
}
test()
{
IniFile inifile;
char szVal[100];
// Read in the .ini file
if (!inifile.read("c:/tempoary/myfile.ini")) // CHANGE THIS PATH
{
printf("Can not read .ini file -- path is probably wrong\n");
return 1;
}
// Get a value as a test
inifile.getSz("mysection", "mykey", szVal, sizeof(szVal));
printf("mykey in mysection = >%s<\n", szVal);
}
A hash isn't good if you want to make changes then write out the file
because order isn't preserved.