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
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:
- The Key Value could not contain an equals sign.
- 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"];
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"];
var key = ini.GetSection("Test")["StringField"];
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;
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:
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"]); Console.WriteLine(ini.GetKeyValue("Test", "StringField"));
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.