首页 / 知识

关于winapi:用C ++解析INI文件最简单的方法是什么?

2023-04-12 07:19:00

关于winapi:用C ++解析INI文件最简单的方法是什么?

What is the easiest way to parse an INI File in C++?

我正在尝试使用C ++解析INI文件。 关于实现此目标的最佳方法的任何技巧? 我应该使用Windows API工具进行INI文件处理(我完全不熟悉),开放源代码解决方案还是尝试手动解析它?


如果您需要跨平台的解决方案,请尝试Boost的程序选项库。


您可以使用Windows API函数,例如GetPrivateProfileString()和GetPrivateProfileInt()。


我从未解析过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

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

然后读取一个值

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

还有很多其他转换器,可将您的INI值转换为标准类型和Qt类型。有关更多信息,请参见QSettings上的Qt文档。


这个问题有点老了,但是我会发表我的答案。我已经测试了各种INI类(您可以在我的网站上看到它们),并且我也使用simpleIni,因为我想同时在Windows和WinCE上使用INI文件。
Window的GetPrivateProfileString()仅与winCE上的注册表一起使用。

使用simpleIni非常容易阅读。这是一个例子:

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

inih是一个用C编写的简单ini解析器,它也带有C ++包装器。用法示例:

1
2
3
4
5
6
7
8
9
#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) <<"\
"
;

作者还在此处提供了现有库的列表。


您是否尝试过libconfig?非常类似于JSON的语法。我更喜欢XML配置文件。


如果您对平台可移植性感兴趣,也可以尝试Boost.PropertyTree。它支持ini作为持久性格式,尽管属性树只能是1级深。


除非您打算跨平台开发该应用程序,否则使用Windows API调用将是最好的方法。只需忽略API文档中有关仅为16位应用程序兼容性而提供的说明。


也许是一个较晚的答案。但是,值得知道的选择。如果您需要跨平台的解决方案,那么绝对可以尝试GLIB,它很有趣。.(https://developer.gnome.org/glib/stable/glib-键值文件-parser.html)


我最终使用了inipp,该线程未提及。

https://github.com/mcmtroffaes/inipp

是MIT许可的仅标头的实现,该实现足够简单,可以添加到项目中并可以使用4行。


我知道这个问题很老,但是我遇到了这个问题,因为我需要一些跨平台的Linux,win32 ...我在下面编写了函数,它是一个可以解析INI文件的函数,希望其他人会发现它有用。

规则和警告:
要解析的buf必须是NULL终止的字符串。将您的ini文件加载到char数组字符串中,然后调用此函数进行解析。
节名称必须在其周围带有[]括号,例如[MySection],而且值和节必须以一行开头且开头不能有空格。它将使用Windows \ r \ n或Linux \ n行尾来解析文件。注释应使用#或//并从文件顶部开始,不得将注释与INI条目数据混合。在返回字符串的两端都删除了引号和刻度。仅当空格在引号之外时才修剪空格。字符串不需要带引号,并且如果缺少引号,则会修剪空格。您还可以提取数字或其他数据,例如,如果您有浮点数,只需在ret缓冲区上执行atof(ret)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//  -----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))!='\
'
){s+=L; goto SearchAgain1;} //section must be at begining of a line!
        s+=L;                                                   //found section, skip past section name
        while(*s!='\
'
){s++;} s++;                              //spin until next line, s is now begining of section data
        e = strstr(s,"\
["
);                                    //find begining of next section or end of file
        if(e){*e=0;}                                            //if we found begining of next section, null the \
 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='\
';}

    #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))!='\
'
){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!='\
'
&& *E!='\
'
&& *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
}

如何使用...示例...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
char sFileData[] ="[MySection]\
\
"

"MyValue1 = 123\
\
"

"MyValue2 = 456\
\
"

"MyValue3 = 789\
\
"

"\
\
"

"[MySection]\
\
"

"MyValue1 = Hello1\
\
"

"MyValue2 = Hello2\
\
"

"MyValue3 = Hello3\
\
"

"\
\
"
;
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]\
"
,str); }
    if(GrabIniValue(sSec,secName,"MyValue2",str,sizeof(str),0))     { printf("MyValue2 = [%s]\
"
,str); }
    if(GrabIniValue(sSec,secName,"MyValue3",str,sizeof(str),0))     { printf("MyValue3 = [%s]\
"
,str); }
    printf("\
"
);
    sSec = next; //parse next section, next will be null if no more sections to parse
}


文件方法工具目标

最新内容

相关内容

热门文章

推荐文章

标签云

猜你喜欢