Estoy tratando de analizar un archivo INI usando C ++. ¿Algún consejo sobre cuál es la mejor manera de lograrlo? ¿Debo usar las herramientas API de Windows para el procesamiento de archivos INI (con las que no estoy familiarizado), una solución de código abierto o intentar analizarlo manualmente?
89
Si necesita una solución multiplataforma, pruebe la biblioteca de opciones de programa de Boost .
fuente
Nunca he analizado archivos ini, por lo que no puedo ser demasiado específico sobre este tema.
Pero tengo un consejo:
no reinventes la rueda siempre que una existente cumpla con tus requisitos.
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
Buena suerte :)
fuente
Si ya está usando Qt
QSettings my_settings("filename.ini", QSettings::IniFormat);
Entonces 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 sobre QSettings para obtener más información.
fuente
sync()
, lo que puede ser una sorpresa) y eso destruye los comentarios y el orden en el que se definieron las variables anteriormente ...Yo uso SimpleIni . Es multiplataforma.
fuente
esta pregunta es un poco antigua, pero publicaré mi respuesta. He probado varias clases INI (puede verlas en mi sitio web ) y también uso simpleIni porque quiero trabajar con archivos INI tanto en Windows como en winCE. GetPrivateProfileString () de Windows solo funciona 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);
fuente
inih es un analizador ini simple escrito en C, también viene con un contenedor C ++. Uso de ejemplo:
#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 aquí .
fuente
¿Ha probado libconfig ; sintaxis muy similar a JSON. Lo prefiero a los archivos de configuración XML.
fuente
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 solo puede tener 1 nivel de profundidad.
fuente
A menos que planee hacer que la aplicación sea multiplataforma, usar las llamadas a la API de Windows sería la mejor manera de hacerlo. Simplemente ignore la nota en la documentación de la API sobre que se proporciona solo para la compatibilidad de aplicaciones de 16 bits.
fuente
Quizás una respuesta tardía ... Pero vale la pena conocer las opciones ... Si necesita una solución multiplataforma, definitivamente puede probar GLIB, es interesante ... ( https://developer.gnome.org/glib/stable/glib- Key-value-file-parser.html )
fuente
Sé que esta pregunta es muy antigua, pero la encontré porque necesitaba algo multiplataforma para Linux, win32 ... Escribí la función a continuación, es una función única que puede analizar archivos INI, espero que otros la encuentren útil.
reglas y advertencias: buf para analizar debe ser una cadena terminada en NULL. Cargue su archivo ini en una cadena de matriz de caracteres y llame a esta función para analizarlo. los nombres de las secciones deben tener [] corchetes alrededor, como este [MySection], también los valores y las secciones deben comenzar en una línea sin espacios iniciales. Analizará archivos con Windows \ r \ n o con finales de línea \ n Linux. Los comentarios deben usar # o // y comenzar en la parte superior del archivo, ningún comentario debe mezclarse con los datos de entrada INI. Las comillas y las marcas se recortan de ambos extremos de la cadena de retorno. Los espacios solo se recortan si están fuera del presupuesto. No es necesario que las cadenas tengan comillas y los espacios en blanco se recortan si faltan comillas. También puede extraer números u otros datos, por ejemplo, si tiene un flotante, simplemente realice un atof (ret) en el búfer 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 }
fuente
Terminé usando inipp que no se menciona en este hilo.
https://github.com/mcmtroffaes/inipp
Era una implementación de encabezado con licencia del MIT que era lo suficientemente simple como para agregar a un proyecto y 4 líneas para usar.
fuente