Я пытаюсь разобрать INI-файл с помощью C ++. Какие-нибудь советы о том, как лучше всего этого добиться? Следует ли мне использовать инструменты Windows API для обработки файлов INI (с которыми я совершенно не знаком), решение с открытым исходным кодом или пытаться разобрать его вручную?
89
Если вам нужно кроссплатформенное решение, попробуйте библиотеку параметров программы Boost .
источник
Я никогда не разбирал 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
Удачи :)
источник
Если вы уже используете Qt
QSettings my_settings("filename.ini", QSettings::IniFormat);
Затем прочтите значение
my_settings.value("GroupName/ValueName", <<DEFAULT_VAL>>).toInt()
Существует множество других конвертеров, которые преобразуют ваши значения INI как в стандартные типы, так и в типы Qt. Дополнительную информацию смотрите в документации Qt по QSettings.
источник
sync()
, что может быть сюрпризом), и это уничтожает комментарии и порядок, в котором переменные были определены ранее ...Я использую SimpleIni . Это кроссплатформенный.
источник
этот вопрос немного устарел, но я опубликую свой ответ. Я протестировал различные классы 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.PropertyTree. Он поддерживает ini как постоянный формат, хотя дерево свойств может быть только на 1 уровень.
источник
Если вы не планируете делать приложение кроссплатформенным, использование вызовов Windows API было бы лучшим способом. Просто проигнорируйте примечание в документации API о том, что оно предоставляется только для совместимости с 16-битными приложениями.
источник
Может быть, поздний ответ ... Но стоит знать варианты ... Если вам нужно кроссплатформенное решение, определенно вы можете попробовать GLIB, это интересно .. ( https://developer.gnome.org/glib/stable/glib- Ключ-значение-файл-парсер.html )
источник
Я знаю, что этот вопрос очень старый, но я натолкнулся на него, потому что мне нужно что-то кросс-платформенное для linux, win32 ... Я написал функцию ниже, это единственная функция, которая может анализировать файлы INI, надеюсь, другие сочтут это полезным.
правила и предостережения: buf для синтаксического анализа должен быть строкой с завершающим NULL. Загрузите ваш 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 }
источник
В итоге я использовал inipp, который не упоминается в этой теме.
https://github.com/mcmtroffaes/inipp
Это была реализация только заголовков, лицензированная MIT, которую было достаточно просто добавить в проект и использовать 4 строки.
источник