INI File Reader

In this tutorial we’re going to create a class that will allow us to read and get data from an .ini file in c#.

Prerequisite

INI file format

Ini file are used as settings files and they have a structure like this:

1
2
3
4
5
6
7
[section1]
name1 = value
name2 = value

[section2]
name1 = value
name2 = value

Ini file are subdivided into section, each of those have at least one key, and each key have a value.
[...] this identify a section, inside it you can write any name.
name1 = value name1 is the name of the key, value is the value of the key.
Every key is associated to the last section, and there can’t be multiple keys with the same name inside the same section.

We saw its structure, so now we can write the code to read it.
Create a new Windows Form project, and you’re ready to start 😄

The class(es)

To write the code of the class we are going to use some list and nested classes.
Nested classes are classes defined inside another class.
Add a new class to the project, then on top add:

1
using System.IO

Now we’ll create the first class that will allow us to read an .ini file.

1
2
3
4
public class INIFile
{

}

Inside this let’s add:

1
public List<Section> sectionList = new List<Section>();

We’ll define the class Section later.
Then we add a function to read the file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void LoadINIFile(string fileName)
{
    string curSection = null;
    string curKey = null;
    string curValue = null;
    foreach (string line in File.ReadLines(fileName))
    {
        if (line.StartsWith("["))
        {
            curSection = line.Substring(1, line.Length - 2);
            if(GetSection(curSection) == null)
            {
                sectionList.Add(new Section() { sectionName = curSection });
            }
        }
        else if (line.Contains("="))
        {
            curKey = line.Split(char.Parse("="))[0];
            curValue = line.Split(char.Parse("="))[1];
            GetSection(curSection).SetKeyValue(curKey.Trim(), curValue.Trim());
        }
    }
}

Inside the foreach function it will read the file fileName line by line.
if (line.StartsWith("[")) if this is true then this is a section, if this section is not inside our list then we add it.
else if (line.Contains("=")) this is a line with a key and its value, so we split the string into 2 pices one before and one after the “=” then we add these to the Section object.
We called the Trim() function to eliminate any white spaces.

Inside this function we called some function that we didn’t make yet, so let’s add them:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public Section GetSection(string section)
{
    Section result = null;
    foreach(Section s in sectionList)
    {
        if(s.sectionName == section)
        {
            result = s;
        }
    }
    return result;
}

This function allow us to find a section in our list, it will return null if it don’t find it.

Section Class

Now we can create the Section class, so let’s add it inside the INIFile class:

1
2
3
4
5
6
7
public class Section : IEquatable<Section>
{
	public bool Equals(Section other)
	{
	    throw new NotImplementedException();
	}
}

We use IEquatable<Section> because we made a list of it.
public bool Equals(Section other) we need to add this because we used IEquatable<Section>, if called it will show the message NotImplementedException.
Let’s add some variables to this class:

1
2
public string sectionName;
public List<Key> keyList = new List<Key>();

sectionName this is the name of the section.
keyList this is a list of all the keys of the section.
We can now add a function to read a value of a key:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public string GetKeyValue(string key)
{
    string result = null;
    foreach(Key k in keyList)
    {
        if(k.keyName == key)
        {
            result = k.keyValue;
        }
    }
    return result;
}

This will search for the key inside the list, if it find it, it will return its value, otherwise it will return null.
As we saw earlier we need also to set or add a key and its value, to do so we need to create a new function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public void SetKeyValue(string key, string value)
{
    bool found = false;
    foreach (Key k in keyList)
    {
        if(k.keyName == key)
        {
            found = true;
            k.keyValue = value;
        }                    
    }
    if(found == false)
    {
        keyList.Add(new Key() { keyName = key, keyValue = value });
    }
}

This function will search for the key, if it doesn’t exit it will add the new kay to the keyList, otherwise it will set the new value to the key.

Key Class

The last class that we need to make is the key class, this one is nested inside the section class, let’s define it:

1
2
3
4
5
6
7
public class Key : IEquatable<Key>
{
	public bool Equals(Key other)
    {
        throw new NotImplementedException();
    }
}

IEquatable<Key> We created a list of keys, so just like the section class we need to add this.
public bool Equals(Key other) We need to add this because of IEquatable.
Inside this class we just need to add two variables, one will be the name of the key, the other will be the value:

1
2
public string keyName;
public string keyValue = "0";

I set the value of the key to “0” if its not specified.

Use the class

We now have created the class, so now we can test it.
I created a simple ini file called config.ini, I put it inside the working directory of our application.
Inside it I’ve wrote:

1
2
3
4
5
6
7
[Section1]
par1 = 123
par2 = abc

[Section2]
par1 = 456
par2 = def

Add a new button to our windows form, and double click it, then we can add some code to the Form:

1
INIFile inf = new INIFile();

This will initialize our new class.
Inside the button click event add:

1
2
inf.LoadINIFile("config.ini");
MessageBox.Show(inf.GetSection("Section2").GetKeyValue("par2"));

inf.LoadINIFile will load the ini file.
MessageBox.Show this will show a message window.
inf.GetSection("Section2") .GetKeyValue("par2") this will give to us the value of the key par2 of the section Section2.
Calling this function, with the ini file that show to you earlier, will return the value def.
Responsive image

Remember, every value returned by the class will be a string.
As always you can see the full source code inside the next section.

Source Code

INIFIle.cs

  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
100
101
102
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace INIProject
{
    class INIFile
    {
        public List<Section> sectionList = new List<Section>();

        public void LoadINIFile(string fileName)
        {
            string curSection = null;
            string curKey = null;
            string curValue = null;
            foreach (string line in File.ReadLines(fileName))
            {
                if (line.StartsWith("["))
                {
                    curSection = line.Substring(1, line.Length - 2);
                    if (GetSection(curSection) == null)
                    {
                        sectionList.Add(new Section() { sectionName = curSection });
                    }
                }
                else if (line.Contains("="))
                {
                    curKey = line.Split(char.Parse("="))[0];
                    curValue = line.Split(char.Parse("="))[1];
                    GetSection(curSection).SetKeyValue(curKey.Trim(), curValue.Trim());
                }
            }
        }

        public Section GetSection(string section)
        {
            Section result = null;
            foreach (Section s in sectionList)
            {
                if (s.sectionName == section)
                {
                    result = s;
                }
            }
            return result;
        }

        public class Section : IEquatable<Section>
        {
            public string sectionName;
            public List<Key> keyList = new List<Key>();

            public bool Equals(Section other)
            {
                throw new NotImplementedException();
            }

            public string GetKeyValue(string key)
            {
                string result = null;
                foreach (Key k in keyList)
                {
                    if (k.keyName == key)
                    {
                        result = k.keyValue;
                    }
                }
                return result;
            }
            public void SetKeyValue(string key, string value)
            {
                bool found = false;
                foreach (Key k in keyList)
                {
                    if (k.keyName == key)
                    {
                        found = true;
                        k.keyValue = value;
                    }
                }
                if (found == false)
                {
                    keyList.Add(new Key() { keyName = key, keyValue = value });
                }
            }

            public class Key : IEquatable<Key>
            {
                public string keyName;
                public string keyValue = "0";
                public bool Equals(Key other)
                {
                    throw new NotImplementedException();
                }
            }

        }
    }
}

Form1.cs

 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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace INIProject
{
    public partial class Form1 : Form
    {
        INIFile inf = new INIFile();
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            inf.LoadINIFile("config.ini");
            MessageBox.Show(inf.GetSection("Section2").GetKeyValue("par2"));
        }
    }
}

Form1.Designer.cs

 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
namespace INIProject
{
    partial class Form1
    {
        private System.ComponentModel.IContainer components = null;
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(12, 12);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.button1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

        private System.Windows.Forms.Button button1;
    }
}

Conclusion

Well done, now you can easly read data from a .ini file! 😄

Did you liked this tutorial?
Did you find it useful?
Let me know on Twitter! @CodeSailer