Write and read configuration file

I can see that some open source software's configuration file were written in the following format:

"<setting name> = <value>".

For my program, it is not necessary to follow the above format. Any format can be acceptable.

I would appreciate if anyone can have tutorial on how to create, read, and write configuration files, or introduce me any library that I should use.

Thank you!
Last edited on
Looks like .ini to me.

Under Windows, the "ini" - file format is very common because then you can use functions like "GetPrivateProfileString" to read them in without fizzling around with file handlers and anything (and you can move it to the registry later without even recompiling).

For other libraries, you may look at Boost.Program_options library. It's cross platform and said to be easy to use. It was intended for command line parameter but can read in from files as well.

Never bothered about config writing, though. I use notepad for this *g*.

Ciao, Imi.
A very simple configuration file handler:

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
#include <iostream>
#include <map>
#include <string>

namespace configuration
  {

  //---------------------------------------------------------------------------
  // The configuration::data is a simple map string (key, value) pairs.
  // The file is stored as a simple listing of those pairs, one per line.
  // The key is separated from the value by an equal sign '='.
  // Commentary begins with the first non-space character on the line a hash or
  // semi-colon ('#' or ';').
  //
  // Example:
  //   # This is an example
  //   source.directory = C:\Documents and Settings\Jennifer\My Documents\
  //   file.types = *.jpg;*.gif;*.png;*.pix;*.tif;*.bmp
  //
  // Notice that the configuration file format does not permit values to span
  // more than one line, commentary at the end of a line, or [section]s.
  //   
  struct data: std::map <std::string, std::string>
    {
    // Here is a little convenience method...
    bool iskey( const std::string& s ) const
      {
      return count( s ) != 0;
      }
    };

  //---------------------------------------------------------------------------
  // The extraction operator reads configuration::data until EOF.
  // Invalid data is ignored.
  //
  std::istream& operator >> ( std::istream& ins, data& d )
    {
    std::string s, key, value;

    // For each (key, value) pair in the file
    while (std::getline( ins, s ))
      {
      std::string::size_type begin = s.find_first_not_of( " \f\t\v" );

      // Skip blank lines
      if (begin == std::string::npos) continue;

      // Skip commentary
      if (std::string( "#;" ).find( s[ begin ] ) != std::string::npos) continue;

      // Extract the key value
      std::string::size_type end = s.find( '=', begin );
      key = s.substr( begin, end - begin );

      // (No leading or trailing whitespace allowed)
      key.erase( key.find_last_not_of( " \f\t\v" ) + 1 );

      // No blank keys allowed
      if (key.empty()) continue;

      // Extract the value (no leading or trailing whitespace allowed)
      begin = s.find_first_not_of( " \f\n\r\t\v", end + 1 );
      end   = s.find_last_not_of(  " \f\n\r\t\v" ) + 1;

      value = s.substr( begin, end - begin );

      // Insert the properly extracted (key, value) pair into the map
      d[ key ] = value;
      }

    return ins;
    }

  //---------------------------------------------------------------------------
  // The insertion operator writes all configuration::data to stream.
  //
  std::ostream& operator << ( std::ostream& outs, const data& d )
    {
    data::const_iterator iter;
    for (iter = d.begin(); iter != d.end(); iter++)
      outs << iter->first << " = " << iter->last << endl;
    return outs;
    }

  } // namespace configuration 

Use it thusly:
1
2
3
4
5
6
7
8
9
10
#include "configuration.h";

int main()
  {
  configuration::data myconfigdata;
  ifstream f( "myprog.ini" );
  f >> myconfigdata;
  f.close();
  ...
  }

I just typed this up, so typos and small errors may exist.

It is simple, but sufficient for many small programs. Every program is different. You may need to modify it somewhat to add functionality that you desire. For example, you can add the power to convert values to ints, or the like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
#include <sstream>
...

  // Gets an integer value from a key. If the key does not exist, or if the value
  // is not an integer, throws an int exception.
  //
  int getintvalue( const std::string& key )
    {
    if (!iskey( key )) throw 0;
    std::istringstream ss( this->operator [] ( key ) );
    int result;
    ss >> result;
    if (!ss.eof()) throw 1;
    return result;
    }


Hope this helps. More advanced solutions exist online if you need.
Topic archived. No new replies allowed.