Click here to Skip to main content
Click here to Skip to main content

Simplified INI Handling

, 24 Jan 2012
Rate this:
Please Sign up or sign in to vote.
An easy to use managed class to handle INI files.

Introduction 

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. 

Background

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");
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. 

History 

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

License

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

About the Author

formlesstree4
Student
United States United States
I am a professional Software Developer at Digital Alchemy. 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.
Follow on   Twitter   LinkedIn

Comments and Discussions

 
Questiongood work Pinmemberzofi5112-Dec-12 21:38 
QuestionDownload Not Available (Still?) PinmemberSqueaker14-Oct-12 11:57 
AnswerRe: Download Not Available (Still?) Pinmembermocha9531-Oct-12 16:49 
BugDownload not avalaible. PinmemberMember 398504227-May-12 20:05 
GeneralRe: Download not avalaible. Pinmemberformlesstree427-May-12 20:07 
BugCan not load a key that its value contain '=' PinmemberBehzad Ebrahimi17-Apr-12 5:22 
AnswerRe: Can not load a key that its value contain '=' Pinmemberformlesstree417-Apr-12 6:06 
I was about to type this long response until I re-read your problem. I thought you were talking about the key name having multiple equal signs, which I was going to chuckle at. But that is a real problem. I shall fix it and have a new version up sometime in the near future. I have a version already that is improved, but it would still fail at that.
NewsRe: Can not load a key that its value contain '=' Pinmemberformlesstree418-Apr-12 21:11 
QuestionVery useful! I like it! PinmemberJalapeno Bob8-Mar-12 9:42 
AnswerRe: Very useful! I like it! Pinmemberformlesstree48-Mar-12 20:53 
QuestionSome extensions you might want to use PinmemberHarm Salomons31-Jan-12 20:33 
AnswerRe: Some extensions you might want to use Pinmemberformlesstree42-Feb-12 13:15 
QuestionAlso change ... PinmemberKlaus Ruttkowski25-Jan-12 22:18 
AnswerRe: Also change ... Pinmemberformlesstree42-Feb-12 13:16 
QuestionMy vote of 5, but ... [modified] PinmemberKlaus Ruttkowski25-Jan-12 21:50 
AnswerRe: My vote of 5, but ... PinmemberQwertie1-Feb-12 10:40 
AnswerRe: My vote of 5, but ... Pinmemberformlesstree42-Feb-12 13:15 
Questionuseful! Pinmemberpoi11924-Jan-12 19:33 
GeneralMy vote of 5 Pinmemberfredatcodeproject24-Jan-12 6:57 

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.140709.1 | Last Updated 24 Jan 2012
Article Copyright 2012 by formlesstree4
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid