Read all the key value pairs from the ini file

Hi team,
My ini file looks like-

[SECTION]
key1=12
key2=14
key3=13

and so on.....

what i want to do is to retreive all the key-value pairs data.
I tried using GetPrivateProfileSection function but with this i am able to get only first pair i.e key1=12. Nothing else. So i need help here.
Hi, wesly....
Can you give us at least an attempt?
Hi jackson,
Are u asking for code?
I tried using GetPrivateProfileSection function...


No... I haven't been using GetPrivateProfileSection function for many years. I usually use 'GetPrivateProfileString'.

My function :
1
2
3
4
5
6
7
8
9
char* GetIniString(const char *IniFile, const char *section, const char *name, char *buffer, const char *def_val = 0){

int len = strlen(buffer);

if(IniFile) GetPrivateProfileString(section, name, def_val, buffer, len, IniFile);
else strcpy(buffer, def_val);

return buffer;
}


Usage :

[SECTION]
key1=12
key2=14
key3=13



1
2
3
4
5
6
7
8
int key1, key2, key3;
char value[256];
GetIniString("IniTest.ini", "SECTION", "key1", value, "0");
key1 = atoi(value);
GetIniString("IniTest.ini", "SECTION", "key2", value, "0");
key2 = atoi(value);
GetIniString("IniTest.ini", "SECTION", "key3", value, "0");
key3 = atoi(value);


Short (But complex) :
1
2
3
4
5
6
7
8
9
int key[3];
char value[256];
char name[64];
strcpy(name,"key0");
     for(int i = 0;i < 3;i++)
         {name[3]++;
          GetIniString("IniTest.ini", "SECTION", name, value, "0");
          key[i] = atoi(value);
         }


Any trouble?
Last edited on
yes i am also using the GetPrivateProfileString function for getting the key values but in this case we need to give the key name rigtht {GetPrivateProfileString("SECTION",NULL,"fail",chValue,25500,value);}
if u give the key name it will return the value.but i need to get all the key value pairs under the [SECTION].
Done ! (See my previous post)

And anything else?

Hope this helps.
Last edited on
Hi jackson ,
this will work for only if we have less number of keys right.....in my ini file more than 100 number of keys are there for that any way is there ...because it is very difficult to initiate many keys right.....

[SECTION]
key1=12
key2=14
key3=13
:
:
key1000=56
..............?!??!?!?!?!!??!!??!?!
Your INI contains 1000 elements, right?????

In your case, you'll need to use the complex code : (But it'll be modified st)

1
2
3
4
5
6
7
8
9
10
11
12
13
int key[1000]; 
char value[256];
char name[64];
char number[10];


     for(int i = 0;i < 1000;i++)
         {strcpy(name,"key");
           itoa(i,number,10); //Convert number -> string
           strcat(name,number);
          GetIniString("IniTest.ini", "SECTION", name, value, "0");
          key[i] = atoi(value);
         }


Any mistake?
hi jackson,
I have one doubt is that in ini file every line has any EOL character?
Yes, every line in a INI file has an EOL character.
Last edited on
Please can u mention any specific character
Hi

The problem with Jackson Marie's approach is that it presumes you know the key names. If you do know them, then GetPrivateProfileString (and GetPrivateProfileInt) is a good way to go. But if you need to discover the key names, then you need to use GetPrivateProfileSection instead.

The reason you only saw the first name-value pair is because the text returned by GetPrivateProfileSection contains embedded nulls. So you've got to jump over them. e.g. (in C++ notation)

"key1=12\0key2=14\0key3=13\0\0"

If you're using a pointer based approach, you start off with your pointer (e.g. pSubstr) at the start of the buffer. Then you advance it by strlen(pSubstr) + 1 (the +1 is what jumps over the null.) The double null (i.e. an empty string) at the end is what allows you to spot the actual end of the data (you'll hit that second null when you jump over the last of those which marks the end of an actual substring.)

The following code shows how to do this. Note that it's up to you to split the name-value pairs on the '=' char. Also note there's minimal error handling in this code.

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// test.cpp

#define WIN32_LEAN_AND_MEAN
// Exclude rarely-used stuff from Windows headers
#include <windows.h>

#include <iostream>
#include <string>
#include <vector>

typedef std::pair<std::string, std::string> NameValuePair;

void
loadIniFile( const std::string&          iniFilePath,
             const std::string&          sectionName,
             std::vector<NameValuePair>& nameValuePairs ) {
    const int bufferSize = 10000;
    char buffer[bufferSize] = "";

    int charsRead = 0;

    charsRead = GetPrivateProfileSection( sectionName.c_str(),
                                          buffer,
                                          bufferSize,
                                          iniFilePath.c_str() );
    // if there isn't enough space, returns bufferSize - 2

    // if we got some data...
    if( (0 < charsRead) && ((bufferSize - 2) > charsRead) ) {
        // walk the buffer extracting values

        // start at the beginning (const to remind us not to
        // change the contents of the buffer)
        const char* pSubstr = buffer;

        // while we have non-empty substrings...
        while('\0' != *pSubstr) {
            // length of key-value pair substring
            size_t substrLen = strlen(pSubstr);

            // split substring on '=' char
            const char* pos = strchr(pSubstr, '=');
            if(NULL != pos) {
                // todo: remove "magic number" for buffer size 
                char name [256] = "";
                char value[256] = "";

                // if you're not using VC++ you'll prob. need to replace
                // _countof(name) with sizeof(name)/sizeof(char) and
                // similarly for value. Plus replace strncpy_s with plain
                // old strncpy.
                strncpy_s(name , _countof(name), pSubstr, pos - pSubstr);
                strncpy_s(value, _countof(value), pos + 1, substrLen - (pos - pSubstr));

                nameValuePairs.push_back(NameValuePair(name, value));
            }

            // jump over the current substring plus its null
            pSubstr += (substrLen + 1);
        }
    }
}

void dumpNameValuePairs(const std::vector<NameValuePair>& nameValuePairs) {
    typedef std::vector<NameValuePair>::size_type size_type;

    const size_type count = nameValuePairs.size();

    for(size_type index = 0; count > index; ++index) {
        const NameValuePair nameValuePair = nameValuePairs[index];
        std::cout << nameValuePair.first << " = " << nameValuePair.second << "\n";
    }

    std::cout << std::endl;
}

int main(int argc, char* argv[]) {
    if(3 != argc) {
        std::cerr << "ini section dump test\n"
            "\n"
            "test.exe ini-file-path section-name\n"
            "\n"
            "Notes\n"
            "- full path to ini-file must be specified, or Windows will\n"
            "  assume the file is in the Windows folder (typically C:\\Windows)\n"
            "- paths and section names containing spaces must be quoted" << std::endl;
    } else {
        std::string iniFilePath = argv[1];
        std::string sectionName = argv[2];

        std::vector<NameValuePair> nameValuePairs;

        loadIniFile(iniFilePath, sectionName, nameValuePairs);

        dumpNameValuePairs(nameValuePairs);
    }

    return 0;
}


for the following ini file

1
2
3
4
5
6
7
; hello.ini

[message]
message text=hello world
sender=andywestken
recipient=wesly
website=cplusplus


and the command line (adjust your file path as required...)

test.exe w:\testing\hello.ini message

the output is

message text = hello world
sender = andywestken
recipient = wesly
website = cplusplus

Andy

PS Regarding

I have one doubt is that in ini file every line has any EOL character

An ini-file is just a text file with either a section name or key name-value pair per line (plus blank and comment lines). So it (the file) has plenty of EOLs (if edited using Notepad.exe, etc. they'll be the normal Windows version. i.e. the pair of chars, \r\n).

But the ini-file API never returns them to you, so they are not relevant to the ini-file reading code, unless you open an ini-file and parse it directly yourself (e.g. using ifstream). When multiple values are returned, they're separated by the null char ('\0') as mentioned above.

PPS If you have a single ini-file section with 1000 name-value pairs, you prob. need to rethink how you're storing your data!

Incidentally, if you need a list of the sections in an ini-file, the code above should more or less work with GetPrivateProfileSectionNames. But while the section names are also separated by nulls, there is no value to split from the name.
Last edited on
Thanks, I didn't know that. :)
Seems I have to make a new INI parsing class, not just an INI function.
Last edited on
Rule of thumb: don't use platform-specific code for dealing with platform-independent formats.
Topic archived. No new replies allowed.