Какой самый простой способ для анализа файла INI в C ++?

Я пытаюсь проанализировать INI-файл с помощью C ++. Любые советы о том, как лучше всего добиться этого? Должен ли я использовать инструменты Windows API для обработки файлов INI (с которыми я совершенно незнаком), решение с открытым исходным кодом или попытаться разобрать его вручную?

15.08.2008 19:31:01
13 ОТВЕТОВ
РЕШЕНИЕ

Вы можете использовать функции Windows API, такие как GetPrivateProfileString () и GetPrivateProfileInt () .

111
15.08.2008 20:06:53
GetPrivateProfileInt () и другие функции не рекомендуются MSDN, поскольку они устарели и по-прежнему предоставляются только для базовой совместимости со старыми 16-разрядными системами. Вместо этого используйте другой подход. msdn.microsoft.com/en-us/library/windows/desktop/...
Zdeno Pavlik 21.02.2018 10:59:50

Я никогда не анализировал 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

Удачи :)

22
15.08.2008 19:40:48

Если вы не планируете сделать приложение кроссплатформенным, лучше всего использовать вызовы Windows API. Просто игнорируйте примечание в документации API о том, что оно предоставляется только для совместимости с 16-битными приложениями.

2
15.08.2008 20:10:46

Если вам нужно кроссплатформенное решение, попробуйте библиотеку Boost's Program Options .

113
10.09.2008 06:37:08
я бы тоже предложил эту библиотеку
varnie 4.11.2009 10:31:19
это путь, я не понимаю, почему люди просто голосуют за не столь общий ответ.
Ramadheer Singh 14.07.2010 22:49:24
@ Голлум, звучит так, будто Windows - это заданная зависимость. Использование библиотеки параметров программы означает получение другой зависимости. Иногда это не имеет большого значения, иногда это так.
I. J. Kennedy 28.06.2011 01:39:05
@malat Я в замешательстве, я не упомянул о понижении голосов?
sjdowling 12.01.2015 13:49:54
Он пытается прочитать существующий INI-файл. Использование boost не является ответом, потому что он использует INI-подобный формат.
Lothar 3.12.2015 02:30:05

Я использую SimpleIni . Это кроссплатформенный.

16
30.10.2015 15:25:37
SimpleIni теперь размещается в Github.
Richard Ye 14.11.2014 02:24:50

Вы пробовали libconfig ; очень JSON-подобный синтаксис. Я предпочитаю это файлам конфигурации XML.

4
16.12.2008 17:13:30

этот вопрос немного старый, но я опубликую свой ответ. Я протестировал различные классы 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);
8
26.12.2009 22:11:04

Если вы уже используете Qt

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

Затем прочитайте значение

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

Существует множество других конвертеров, которые преобразуют ваши значения INI как в стандартные типы, так и в типы Qt. Для получения дополнительной информации смотрите документацию Qt по QSettings.

15
3.12.2010 07:21:03
Неплохо, хотя, если вы вносите изменения, они сохраняют их обратно в файл .ini, фактически не сообщая вам (т. Е. Вызовы деструктора sync(), что может быть сюрпризом), и это разрушает комментарии и порядок, в котором переменные были определены ранее ...
Alexis Wilke 29.08.2016 02:35:03

Если вы заинтересованы в переносимости платформы, вы также можете попробовать Boost.PropertyTree. Он поддерживает ini как постоянный формат, хотя дерево свойств может быть только на 1 уровне глубины.

3
18.03.2013 19:40:28

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

У автора также есть список существующих библиотек здесь .

6
13.08.2013 12:51:41

Возможно, поздний ответ ... Но стоит знать варианты ... Если вам нужно кроссплатформенное решение, определенно вы можете попробовать GLIB, это интересно .. ( https://developer.gnome.org/glib/stable/glib- Key-value-file-parser.html )

1
9.02.2015 17:36:16

Я знаю, что этот вопрос очень старый, но я натолкнулся на него, потому что мне нужно что-то кроссплатформенное для linux, win32 ... Я написал функцию ниже, это единственная функция, которая может анализировать файлы INI, надеюсь, другие найдут ее полезной.

rules & caveats: buf для анализа должен быть строкой с нулевым символом в конце. Загрузите ваш INI-файл в строку массива char и вызовите эту функцию для его анализа. имена разделов должны иметь квадратные скобки [], такие как [MySection], также значения и разделы должны начинаться на строке без пробелов. Он будет анализировать файлы в Windows \ r \ n или в конце строки \ n Linux. Комментарии должны использовать # или // и начинаются в верхней части файла, никакие комментарии не должны смешиваться с данными ввода 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
}
0
10.01.2018 15:50:40

Я закончил тем, что использовал inipp, который не упомянут в этой теме.

https://github.com/mcmtroffaes/inipp

Была реализация только для заголовка MIT, которая была достаточно проста, чтобы добавить в проект и использовать 4 строки.

0
8.04.2019 20:11:03