Какой самый простой способ проанализировать файл INI в C++?
Я пытаюсь разобрать INI-файл с помощью C++. Любые советы о том, что это лучший способ достичь этого? Должен ли я использовать инструменты Windows API для обработки INI-файлов (с которыми я совершенно не знаком), решение с открытым исходным кодом или попытаться проанализировать его вручную?
12 ответов:
вы можете использовать функции Windows API, такие как GetPrivateProfileString() и GetPrivateProfileInt().
Если вам нужно кросс-платформенное решение, попробуйте Boost's Параметры Программы библиотека.
Я никогда не анализировал ini-файлы, поэтому я не могу быть слишком конкретным по этому вопросу.
Но у меня есть один совет:
не изобретайте колесо до тех пор, пока существующее соответствует вашему требования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удачи :)
Я использую SimpleIni. Это кросс-платформенный.
Если вы уже используете Qt
QSettings my_settings("filename.ini", QSettings::IniFormat);затем считайте значение
my_settings.value("GroupName/ValueName", <<DEFAULT_VAL>>).toInt()есть куча других конвертеров, которые преобразуют ваши значения INI как в стандартные типы, так и в типы Qt. Видим в Qt документации на расширений для получения дополнительной информации.
этот вопрос немного старый, но я опубликую свой ответ. Я тестировал различные классы INI (вы можете увидеть их на моем сайт) и я также использую simpleIni, потому что я хочу работать с INI-файлами как на windows, так и на winCE. Окно GetPrivateProfileString () работает только с реестром на winCE.
это очень легко читать с simpleIni. Вот пример:
#include "SimpleIni\SimpleIni.h" CSimpleIniA ini; ini.SetUnicode(); ini.LoadFile(FileName); const char * pVal = ini.GetValue(section, entry, DefaultStr);
inih Это простой парсер ini, написанный на C, он также поставляется с оболочкой C++. Пример использования:
#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";у автора также есть список существующих библиотек здесь.
вы пробовали libconfig; очень JSON-подобный синтаксис. Я предпочитаю его над файлами конфигурации XML.
Если вы заинтересованы в переносимости платформы, вы также можете попробовать Boost.Недвижимость. Он поддерживает ini как формат постоянства, хотя дерево свойств my be 1 level deep только.
Если вы не планируете делать приложение кросс-платформенным,использование вызовов API Windows будет лучшим способом. Просто проигнорируйте примечание в документации API о том, что оно предоставляется только для 16-разрядной совместимости приложений.
может быть поздний ответ..Но, стоит знать варианты..Если вам нужно кросс-платформенное решение, определенно вы можете попробовать GLIB,, его интересно.. (https://developer.gnome.org/glib/stable/glib-Key-value-file-parser.html)
Я знаю, что этот вопрос очень старый, но я наткнулся на него, потому что мне нужно было что-то кросс-платформенное для linux, win32... Я написал функцию ниже, это единственная функция, которая может анализировать INI-файлы, надеюсь, другие найдут ее полезной.
правила и предостережения: buf для синтаксического анализа должна быть строка с нулевым завершением. Загрузите файл ini в строку массива символов и вызовите эту функцию для его анализа. имена разделов должны иметь [] скобки вокруг них, такие как это [MySection], а также значения и разделы должны начинаться на линии без пробелов. Он будет анализировать файлы с Windows \r\n или с Linux \N окончаниями строк. Комментарии должны использовать # или // и начинаться в верхней части файла, никакие комментарии не должны смешиваться с данными ввода INI. Кавычки и тики обрезаются с обоих концов возвращаемой строки. Пробелы обрезаются только в том случае, если они находятся вне кавычки. Строки не обязательно должны иметь кавычки и пробелы обрезаются, если кавычки отсутствуют. Вы также можете извлечь номера или другие данные, например например, если у вас есть float, просто выполните atof (ret) в буфере 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 }Как использовать... образец....
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 }
Comments