Domanda

Sto cercando di analizzare un file INI utilizzando C++.Qualche consiglio su quale sia il modo migliore per raggiungere questo obiettivo?Dovrei utilizzare gli strumenti API di Windows per l'elaborazione dei file INI (con i quali non ho alcuna familiarità), una soluzione open source o tentare di analizzarli manualmente?

È stato utile?

Soluzione

È possibile utilizzare le funzioni API di Windows, come GetPrivateProfileString() E GetPrivateProfileInt().

Altri suggerimenti

Se hai bisogno di una soluzione multipiattaforma, prova Boost Opzioni del programma biblioteca.

Non ho mai analizzato i file ini, quindi non posso essere troppo specifico su questo problema.
Ma ho un consiglio:
Non reinventare la ruota finché quella esistente soddisfa le tue esigenze

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

Buona fortuna :)

Io uso SimpleIni.È multipiattaforma.

Se stai già utilizzando Qt

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

Quindi leggere un valore

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

Esistono molti altri convertitori che convertono i tuoi valori INI sia in tipi standard che in tipi Qt.Consulta la documentazione Qt su QSettings per ulteriori informazioni.

questa domanda è un po' vecchia, ma pubblicherò la mia risposta.Ho testato varie classi INI (puoi vederle sul mio file sito web) e uso anche simpleIni perché voglio lavorare con i file INI sia su Windows che su WinCE.GetPrivateProfileString() di Windows funziona solo con il registro su winCE.

È molto facile da leggere con simpleIni.Ecco un esempio:

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

inih è un semplice parser ini scritto in C, viene fornito anche con un wrapper C++.Utilizzo di esempio:

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

L'autore ha anche un elenco delle biblioteche esistenti Qui.

Hai provato libconfig;sintassi molto simile a JSON.Lo preferisco ai file di configurazione XML.

Se sei interessato alla portabilità della piattaforma, puoi anche provare Boost.PropertyTree.Supporta ini come formato di persistenza, sebbene l'albero delle proprietà possa essere profondo solo 1 livello.

A meno che tu non preveda di rendere l'app multipiattaforma, utilizzare le chiamate API di Windows sarebbe il modo migliore per procedere.Ignora semplicemente la nota nella documentazione dell'API relativa alla fornitura solo per la compatibilità delle app a 16 bit.

Forse una risposta tardiva... Ma vale la pena conoscere le opzioni... Se hai bisogno di una soluzione multipiattaforma, puoi sicuramente provare GLIB, è interessante...(https://developer.gnome.org/glib/stable/glib-Key-value-file-parser.html)

So che questa domanda è molto vecchia, ma mi sono imbattuto perché avevo bisogno di qualcosa multipiattaforma per Linux, Win32...Ho scritto la funzione qui sotto, è una singola funzione in grado di analizzare i file INI, spero che altri la trovino utile.

regole e avvertenze:buf da analizzare deve essere una stringa con terminazione NULL.Carica il tuo file ini in una stringa di array di caratteri e chiama questa funzione per analizzarlo.i nomi delle sezioni devono essere racchiusi tra parentesi [], come questo [MySection], inoltre i valori e le sezioni devono iniziare su una riga senza spazi iniziali.Analizzerà i file con terminazioni di riga Windows o Linux .I commenti dovrebbero usare # o // e iniziare all'inizio del file, nessun commento dovrebbe essere mescolato con i dati di ingresso INI.Le virgolette e i segni di spunta vengono eliminati da entrambe le estremità della stringa restituita.Gli spazi vengono tagliati solo se sono al di fuori della virgoletta.Non è necessario che le stringhe contengano virgolette e gli spazi bianchi vengono tagliati se mancano le virgolette.Puoi anche estrarre numeri o altri dati, ad esempio se hai un float basta eseguire un atof(ret) sul 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
}

Come usare...esempio....

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
}

Ho finito per usare inipp che non è menzionato in questo thread.

https://github.com/mcmtroffaes/inipp

Era un'implementazione di sola intestazione con licenza MIT che era abbastanza semplice da aggiungere a un progetto e 4 righe da utilizzare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top