Was ist der einfachste Weg, um zu analysieren, eine INI-Datei in C++?
Frage
Ich bin versucht zu analysieren, eine INI-Datei mit C++.Irgendwelche Tipps, was ist der beste Weg, dies zu erreichen?Sollte ich das Windows-API-tools für die INI-Datei der Verarbeitung (was mir völlig unbekannt), eine open-source-Lösung oder versuchen zu analysieren Sie diese manuell?
Lösung
Sie verwenden können die Windows-API-Funktionen, wie GetPrivateProfileString() und GetPrivateProfileInt().
Andere Tipps
Wenn Sie benötigen eine cross-Plattform-Lösung, versuchen Sie Steigern die Programm-Optionen Bibliothek.
Ich habe noch nie analysiert ini-Dateien, so kann ich nicht zu spezifisch auf dieses Problem.
Aber ich habe einen Tipp:
Das Rad nicht neu erfinden, solange eine bestehende zu Ihren Anforderungen entspricht
http://en.wikipedia.org/wiki/INI_file#Accessing_INI_files
http://sdl-cfg.sourceforge.net/
http://sourceforge.net/projects/libini/
http://www.codeproject.com/KB/files/config-file-parser.aspx
Gute Glück :)
Ich benutze SimpleIni.Es ist cross-Plattform.
Wenn Sie bereits eine Qt
QSettings my_settings("filename.ini", QSettings::IniFormat);
Lesen Sie dann den Wert
my_settings.value("GroupName/ValueName", <<DEFAULT_VAL>>).toInt()
Es gibt eine Reihe von anderen Konverter, konvertieren Sie Ihre INI-Werte in standard-und Qt-Typen.Siehe Qt-Dokumentation auf QSettings für mehr Informationen.
diese Frage ist ein bisschen alt, aber ich poste meine Antwort.Ich habe getestet, verschiedene INI-Klassen (Sie können finden Sie auf meiner website) und ich nutze auch simpleIni, weil ich wollen, um die Arbeit mit INI-Dateien unter windows und winCE.Fenster GetPrivateProfileString() funktioniert nur mit der Registrierung auf winCE.
Es ist sehr leicht zu Lesen mit simpleIni.Hier ist ein Beispiel:
#include "SimpleIni\SimpleIni.h"
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile(FileName);
const char * pVal = ini.GetValue(section, entry, DefaultStr);
inih ist eine einfache ini-parser in C geschrieben, es kommt mit einer C++ - wrapper zu.Beispiel Verwendung:
#include "INIReader.h"
INIReader reader("test.ini");
std::cout << "version="
<< reader.GetInteger("protocol", "version", -1) << ", name="
<< reader.Get("user", "name", "UNKNOWN") << ", active="
<< reader.GetBoolean("user", "active", true) << "\n";
Der Autor hat auch eine Liste von bestehenden Bibliotheken hier.
Haben Sie versucht, libconfig;sehr JSON-ähnlichen syntax.Ich bevorzuge es über XML-Konfigurationsdateien.
Wenn Sie interessiert sind in der Plattform-Portabilität, Sie können auch versuchen Boost.PropertyTree.Es unterstützt die ini als persistancy format, obwohl die Eigenschaft Baum-mein 1 Ebene tief nur.
Es sei denn, Sie planen, die app, die cross-Plattform, mit der Windows-API-Aufrufe, wäre der beste Weg zu gehen.Ignorieren Sie den Hinweis in der API-Dokumentation über zur Verfügung gestellt nur für 16-bit-app-Kompatibilität.
Vielleicht eine späte Antwort..Aber lohnt sich zu wissen, Optionen..Wenn Sie benötigen eine cross-Plattform-Lösung , auf jeden Fall können Sie versuchen, GLIB,, die interessante..(https://developer.gnome.org/glib/stable/glib-Key-value-file-parser.html)
Ich weiß, diese Frage ist sehr alt, aber ich kam darauf, weil ich etwas brauchte cross-Plattform für linux, win32...Ich habe die Funktion unten, es ist eine einzelne Funktion, können analysieren INI Dateien hoffentlich andere finden es nützlich.
Regeln & Einschränkungen:buf analysiert werden müssen, eine mit NULL beendete Zeichenfolge.Laden Sie Ihre ini-Datei in ein char array, string und rufen Sie diese Funktion analysieren.Abschnitt müssen die Namen haben [] Klammern um Sie herum, wie dieser [MySection], auch Werte und Abschnitte müssen zunächst auf eine Zeile, ohne führende Leerzeichen.Es wird analysiert Dateien unter Windows \ \ \ n oder mit Linux zeilenendungen.Kommentare verwenden sollten, # oder // und beginnen Sie am Anfang der Datei keine Kommentare sollte gemischt werden mit INI-Eintrag-Daten.Zitate und Zecken sind getrimmt von beiden enden der Zeichenkette zurückgeben.Leerzeichen werden nur geschnitten, wenn Sie außerhalb der quote.Strings sind nicht erforderlich, um Anführungszeichen und Leerzeichen abgeschnitten werden, wenn die Anführungszeichen fehlen.Sie können auch extrahieren von zahlen oder anderen Daten, zum Beispiel, wenn Sie einen float-Sie brauchen nur atof(ret) auf die ret-Puffer.
// -----note: no escape is nessesary for inner quotes or ticks-----
// -----------------------------example----------------------------
// [Entry2]
// Alignment = 1
// LightLvl=128
// Library = 5555
// StrValA = Inner "quoted" or 'quoted' strings are ok to use
// StrValB = "This a "quoted" or 'quoted' String Value"
// StrValC = 'This a "tick" or 'tick' String Value'
// StrValD = "Missing quote at end will still work
// StrValE = This is another "quote" example
// StrValF = " Spaces inside the quote are preserved "
// StrValG = This works too and spaces are trimmed away
// StrValH =
// ----------------------------------------------------------------
//12oClocker super lean and mean INI file parser (with section support)
//set section to 0 to disable section support
//returns TRUE if we were able to extract a string into ret value
//NextSection is a char* pointer, will be set to zero if no next section is found
//will be set to pointer of next section if it was found.
//use it like this... char* NextSection = 0; GrabIniValue(X,X,X,X,X,&NextSection);
//buf is data to parse, ret is the user supplied return buffer
BOOL GrabIniValue(char* buf, const char* section, const char* valname, char* ret, int retbuflen, char** NextSection)
{
if(!buf){*ret=0; return FALSE;}
char* s = buf; //search starts at "s" pointer
char* e = 0; //end of section pointer
//find section
if(section)
{
int L = strlen(section);
SearchAgain1:
s = strstr(s,section); if(!s){*ret=0; return FALSE;} //find section
if(s > buf && (*(s-1))!='\n'){s+=L; goto SearchAgain1;} //section must be at begining of a line!
s+=L; //found section, skip past section name
while(*s!='\n'){s++;} s++; //spin until next line, s is now begining of section data
e = strstr(s,"\n["); //find begining of next section or end of file
if(e){*e=0;} //if we found begining of next section, null the \n so we don't search past section
if(NextSection) //user passed in a NextSection pointer
{ if(e){*NextSection=(e+1);}else{*NextSection=0;} } //set pointer to next section
}
//restore char at end of section, ret=empty_string, return FALSE
#define RESTORE_E if(e){*e='\n';}
#define SAFE_RETURN RESTORE_E; (*ret)=0; return FALSE
//find valname
int L = strlen(valname);
SearchAgain2:
s = strstr(s,valname); if(!s){SAFE_RETURN;} //find valname
if(s > buf && (*(s-1))!='\n'){s+=L; goto SearchAgain2;} //valname must be at begining of a line!
s+=L; //found valname match, skip past it
while(*s==' ' || *s == '\t'){s++;} //skip spaces and tabs
if(!(*s)){SAFE_RETURN;} //if NULL encounted do safe return
if(*s != '='){goto SearchAgain2;} //no equal sign found after valname, search again
s++; //skip past the equal sign
while(*s==' ' || *s=='\t'){s++;} //skip spaces and tabs
while(*s=='\"' || *s=='\''){s++;} //skip past quotes and ticks
if(!(*s)){SAFE_RETURN;} //if NULL encounted do safe return
char* E = s; //s is now the begining of the valname data
while(*E!='\r' && *E!='\n' && *E!=0){E++;} E--; //find end of line or end of string, then backup 1 char
while(E > s && (*E==' ' || *E=='\t')){E--;} //move backwards past spaces and tabs
while(E > s && (*E=='\"' || *E=='\'')){E--;} //move backwards past quotes and ticks
L = E-s+1; //length of string to extract NOT including NULL
if(L<1 || L+1 > retbuflen){SAFE_RETURN;} //empty string or buffer size too small
strncpy(ret,s,L); //copy the string
ret[L]=0; //null last char on return buffer
RESTORE_E;
return TRUE;
#undef RESTORE_E
#undef SAFE_RETURN
}
Die Verwendung...Beispiel....
char sFileData[] = "[MySection]\r\n"
"MyValue1 = 123\r\n"
"MyValue2 = 456\r\n"
"MyValue3 = 789\r\n"
"\r\n"
"[MySection]\r\n"
"MyValue1 = Hello1\r\n"
"MyValue2 = Hello2\r\n"
"MyValue3 = Hello3\r\n"
"\r\n";
char str[256];
char* sSec = sFileData;
char secName[] = "[MySection]"; //we support sections with same name
while(sSec)//while we have a valid sNextSec
{
//print values of the sections
char* next=0;//in case we dont have any sucessful grabs
if(GrabIniValue(sSec,secName,"MyValue1",str,sizeof(str),&next)) { printf("MyValue1 = [%s]\n",str); }
if(GrabIniValue(sSec,secName,"MyValue2",str,sizeof(str),0)) { printf("MyValue2 = [%s]\n",str); }
if(GrabIniValue(sSec,secName,"MyValue3",str,sizeof(str),0)) { printf("MyValue3 = [%s]\n",str); }
printf("\n");
sSec = next; //parse next section, next will be null if no more sections to parse
}
Ich landete mit inipp, die nicht erwähnt in diesem thread.
https://github.com/mcmtroffaes/inipp
War ein MIT-lizenziert-header, nur die Umsetzung war einfach genug, um zu einem Projekt hinzufügen und 4 Zeilen zu verwenden.