c++ winapi ini fileparse

¿Cuál es la forma más fácil de analizar un archivo INI en C++?



winapi fileparse (12)

Estoy tratando de analizar un archivo INI usando C ++. ¿Algún consejo sobre cuál es la mejor manera de lograr esto? ¿Debo usar las herramientas de la API de Windows para el procesamiento de archivos INI (que no conozco del todo), una solución de código abierto o intentar analizarla manualmente?


¿Has probado libconfig ? una sintaxis similar a JSON. Lo prefiero sobre los archivos de configuración XML.


A menos que planee hacer la aplicación multiplataforma, usar las llamadas API de Windows sería la mejor manera de hacerlo. Simplemente ignore la nota en la documentación de la API que se proporciona solo para la compatibilidad de aplicaciones de 16 bits.




Sé que esta pregunta es muy antigua, pero me enteré porque necesitaba algo multiplataforma para Linux, Win32 ... escribí la función a continuación, es una función única que puede analizar archivos INI, ojalá que a otros les resulte útil.

rules & advertencias: buf to parse debe ser una cadena terminada NULL. Cargue su archivo ini en una cadena de matriz char y llame a esta función para analizarlo. los nombres de sección deben tener corchetes [] alrededor de ellos, como esta [MiSección], también los valores y las secciones deben comenzar en una línea sin espacios iniciales. Analizará archivos con Windows / r / n o con terminaciones de línea Linux / n. Los comentarios deben usar # o // y comenzar en la parte superior del archivo, no se deben mezclar los comentarios con los datos de entrada de INI. Las comillas y las señales se recortan desde ambos extremos de la cadena de retorno. Los espacios solo se recortan si están fuera de la cita. No se requiere que las cadenas tengan comillas, y los espacios en blanco se recortan si faltan las comillas. También puede extraer números u otros datos, por ejemplo, si tiene un flotador simplemente ejecute un atof (ret) en el buffer ret.

// -----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 }

Cómo usar ... ejemplo ....

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 }


Si está interesado en la portabilidad de la plataforma, también puede probar Boost.PropertyTree. Admite ini como formato de persistencia, aunque el árbol de propiedades puede ser solo de 1 nivel.



Si ya estás usando Qt

QSettings my_settings("filename.ini", QSettings::IniFormat);

Luego lee un valor

my_settings.value("GroupName/ValueName", <<DEFAULT_VAL>>).toInt()

Hay muchos otros convertidores que convierten sus valores INI en tipos estándar y tipos Qt. Consulte la documentación de Qt en QSettings para obtener más información.




esta pregunta es un poco vieja, pero publicaré mi respuesta. He probado varias clases INI (puedes verlas en mi website ) y también uso simpleIni porque quiero trabajar con archivos INI en windows y winCE. Window GetPrivateProfileString () funciona solo con el registro en winCE.

Es muy fácil de leer con simpleIni. Aquí hay un ejemplo:

#include "SimpleIni/SimpleIni.h" CSimpleIniA ini; ini.SetUnicode(); ini.LoadFile(FileName); const char * pVal = ini.GetValue(section, entry, DefaultStr);


inih es un analizador de ini simple escrito en C, viene con un envoltorio de C ++ también. Ejemplo de uso:

#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";

El autor también tiene una lista de bibliotecas existentes here .