Click here to Skip to main content
15,314,526 members
Articles / Programming Languages / C# 4.0
Posted 24 Jan 2012

Tagged as


35 bookmarked

Simplified INI Handling

Rate me:
Please Sign up or sign in to vote.
4.88/5 (13 votes)
24 Jan 2012CPOL5 min read
An easy to use managed class to handle INI files.


I'm pretty sure someone else has done this, but here's my shot at it: a simplified class to handle INI files with absolutely no API calls at all. This class is a shot at an easy way to create and manage INI files almost effortlessly. 


The initial version of this class was severely limited: It only took String, Boolean, and Double. That's a rather limited selection of types, and even then, there were a few different bugs with the way it handled parsing an INI file:

  1. The Key Value could not contain an equals sign.
  2. Comments were not always parsed out properly.

Both of those bugs (there were probably more) are annoying. They stink, and really didn't bring anything more to the table than the API's in Windows already did (which they did without bugs I believe). This is a full scale rewrite of the INI class in an attempt to make it...less buggy and more user friendly and usable.

Using the Code 

The code itself is much easier than before. I took a few ideas from the initial replies in the first article to heart and applied them to the class.

Despite the class being rewritten from the ground up, it still has some similarities from the original library. Although, behind the scenes, a few things have changed dramatically. I will explain those later on in the article.

For now, let's create a simple INI file, with one section called "Test", and a Key called "StringField" with a Value of "Hello World!".

var ini = new INI();
ini.Add("Test", "StringField", "Hello World!");

That's it! That's all there is to it. You have added a Section, and then given that Section one Key with a Value attached to that Key.

Accessing a Section

The simplest thing now is to access that Section we just created. The INILibrary includes a really simple method of doing just that:

var section = ini["Test"];
// or
var section = ini.GetSection("Test"); 

Now, why would I include two different methods of doing this? The first example will never throw an Exception. If a Section does not exist, it will simply add it to the INI, and then return the newly added Section. However, GetSection will  throw an Exception if the Section does not exist. I decided to include both methods to give developers a choice in whatever they write when using this library.

As an alternative, you can also get all the Sections in the INI class with a simple call:

var sections = ini.Sections; 

Accessing a Key 

Okay, so, we know how to get a Section. But, what if I want to get a Key now? There are a few different ways you can get Keys as well, all drawing roots from how we got a Section:

var key = ini["Test"]["StringField"];
// or
var key = ini.GetSection("Test")["StringField"];
// or
var key = ini.GetKey("Test", "StringField");

Goodness, that's three different ways to get a simple key! Okay, here's the breakdown:

Method 1, just like with the Sections, will never throw an Exception. It will simply add the Key (and/or Section) if it doesn't exist (with the Value as an empty String), and return it. That's it, no Exceptions and no questions.

Method 2, as you all should recall, will throw an Exception if the Section doesn't exist. But, it will silently add the Key (with the Value as an empty String) and then give it to you. 

Method 3 will throw an Exception if the Section or Key do not exist. This was included for the same reason as GetSection was included: To give developers a choice of having methods that throw Exceptions to ones that silently add and continue. Whether or not that is bad design choice now lies in the hands of the developer.

Accessing a Key Value

I could go really crazy and give roughly four methods to grabbing Key data, however, I will only give two methods: 

var value = ini["Test"]["StringField"].Value; 
// or
var value = ini.GetKeyValue("Test", "StringField");   

There's a small pattern here that I hope you readers should have recognized by this point:

Method 1: If the Key or Section does not exist, it will add both and assign the key an empty String for its Value. 

Method 2 will throw an Exception if the Section or Key does not exist for again the same reasons that have been explained twice now. 

Saving, Loading, and Merging

New in this version if the INILibrary is the ability to Merge two INI files together. This will, quite simply, take the INI file currently loaded (if applicable), and load in a new INI file. It will merge duplicate sections and ignore keys of the same value that are loaded in. Use this feature at your own risk as it will value the currently loaded INI's field more than the one being imported. 

Now that that warning is out of the way, here is the easy syntax of Saving, Loading, and Merging:

ini.Save("location", Type.INI);
ini.Load("location", Type.INI);
ini.Merge("location", Type.INI);

The "location" refers to the file path to either save to, load from, or merge from. Quite simple and very straightforward. If anyone has requests for additional code examples, or more specific code examples, do not be afraid to ask in the comments as I do check back quite often. 

Points of Interest

This was a fun experiment that really hammered into me that Classes are reference types and Structures are most definitely not. The original design had structures, which I soon found out made manipulating things behind the scene very difficult. It's one reason I can successfully get away with writing code like this with the library:

var key = ini["Test"]["StringField"];
key.Value = "newValue";
Console.WriteLine(ini["Test"]["StringField"]); // Outputs "newValue"
Console.WriteLine(ini.GetKeyValue("Test", "StringField")); // Outputs "newValue" 

However, one should take caution with references. It can lead to some unexpected results if not handled with the appropriate care. However, when handled appropriately, it can have some really nice effects in programming.

Another thing that should be noted is the heavy use of LINQ I use in the program at certain locations. I use it liberally because of the fact that Classes are still reference types, so why not take advantage of the language features that are at hand? I'm not sure if that's a "Point of Interest", but I think it is to me.

XML support is quite limited for the Library. I took the lazy man's route this time around and just used the XmlSerializer instead of writing the document out myself. Merging XML files is -not- supported as of this version. I'm not sure if I can get around to actually supporting the merging myself, but if I can I will incorporate it. 


  • 1/23/2012 - First release.
  • 5/24/2012 - Complete Rewrite, lots of changes! New class written from the ground up. 


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

United States United States
I am a professional Software Developer. I work primarily in C# and interact with Microsoft SQL Server at my job. I have been developing software since I was 15 and continue to learn more and more every day.

Comments and Discussions

GeneralMy vote of 5 Pin
Tsuda Kageyu11-Nov-14 15:09
MemberTsuda Kageyu11-Nov-14 15:09 
Questiongood work Pin
zofi5112-Dec-12 21:38
Memberzofi5112-Dec-12 21:38 
QuestionDownload Not Available (Still?) Pin
Squeaker14-Oct-12 11:57
MemberSqueaker14-Oct-12 11:57 
AnswerRe: Download Not Available (Still?) Pin
Member 355851830-May-15 17:34
MemberMember 355851830-May-15 17:34 
BugDownload not avalaible. Pin
Brontozaurus27-May-12 20:05
MemberBrontozaurus27-May-12 20:05 
GeneralRe: Download not avalaible. Pin
formlesstree427-May-12 20:07
professionalformlesstree427-May-12 20:07 
BugCan not load a key that its value contain '=' Pin
Behzad Ebrahimi17-Apr-12 5:22
MemberBehzad Ebrahimi17-Apr-12 5:22 
For example check the following setting:

strConnectionString=Data Source=;Initial Catalog=DB1;User Id=User1;Password=1234;

AnswerRe: Can not load a key that its value contain '=' Pin
formlesstree417-Apr-12 6:06
professionalformlesstree417-Apr-12 6:06 
NewsRe: Can not load a key that its value contain '=' Pin
formlesstree418-Apr-12 21:11
professionalformlesstree418-Apr-12 21:11 
QuestionVery useful! I like it! Pin
Jalapeno Bob8-Mar-12 9:42
professionalJalapeno Bob8-Mar-12 9:42 
AnswerRe: Very useful! I like it! Pin
formlesstree48-Mar-12 20:53
professionalformlesstree48-Mar-12 20:53 
QuestionSome extensions you might want to use Pin
Harm Salomons31-Jan-12 20:33
MemberHarm Salomons31-Jan-12 20:33 
AnswerRe: Some extensions you might want to use Pin
formlesstree42-Feb-12 13:15
professionalformlesstree42-Feb-12 13:15 
QuestionAlso change ... Pin
Klaus Ruttkowski25-Jan-12 22:18
MemberKlaus Ruttkowski25-Jan-12 22:18 
AnswerRe: Also change ... Pin
formlesstree42-Feb-12 13:16
professionalformlesstree42-Feb-12 13:16 
QuestionMy vote of 5, but ... Pin
Klaus Ruttkowski25-Jan-12 21:50
MemberKlaus Ruttkowski25-Jan-12 21:50 
AnswerRe: My vote of 5, but ... Pin
Qwertie1-Feb-12 10:40
MemberQwertie1-Feb-12 10:40 
AnswerRe: My vote of 5, but ... Pin
formlesstree42-Feb-12 13:15
professionalformlesstree42-Feb-12 13:15 
Questionuseful! Pin
poi11924-Jan-12 19:33
Memberpoi11924-Jan-12 19:33 
GeneralMy vote of 5 Pin
fredatcodeproject24-Jan-12 6:57
professionalfredatcodeproject24-Jan-12 6:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.