Programming Tips - Win32: Quickly read an ini file

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.