This document specifies a text-based file format for representing software configuration data in a format which is easily editable by humans and unambiguously readable by a simple automatic parser.
The format described here is an implementation of the application initialization file format, further refered to as INI file format, written in C#. Since the original Microsoft specification (defined in the Microsoft Windows for Workgroups Resource Kit) is generic, and implementations vary widely, we document how the INI file and parser is implemented here.
Most current implementations are simple, e.g. don't prevail the sequence of sections or don't support comments. In particular, missing support for comments hinders one to process existing INI files. To overcome limitations we wrote our own INI file parser resulting in a complete implementation of INI file format.
An INI file is a text file divided into sections, each containing zero or more keys. Each key contains zero or more values separated by comma. Comment lines are supported before a section name line or a key name line, respectively. Inline comments are comments following a section's name or a key/value pair.
; Comment line (belongs to Section1)
[Section1] ; Inline comment of Section1
Key1=Value1
; Comment line (belongs to Key2)
Key2=Value1 , Value2,Value3 ; Inline comment of Key2
Key3= "Value1"
Section names are enclosed in square brackets, key names are followed by an equal sign. Both names are case-sensitive and both names are optionally surrounded by spacing characters, which are ignored.
Characters not allowed inside of section names are: square brackets, comma, semicolon, double quotation mark, and whitespace.
Characters not allowed inside of key names are: sign of equality, comma, semicolon, double quotation mark, and whitespace.
If the same section appears more than once in the same file, or if the same key appears more than once in the same section, then the last occurrence prevails.
When a parser encounters an unrecognized section name, the entire section (with all its keys) will be skipped. Within a known section, only unrecognized keys will be skipped.
Values are always string values, no types or implicit type conversions are supported. Values may optionally be enclosed in double quotation marks. Values beginning or ending with whitespace characters, or containing commas or semicolons, must be enclosed in double quotation marks. Double quotation marks appearing inside of a value enclosed in double quotation marks must be encoded as an escape sequence, containing a backslash followed by a double quotation mark: \".
Escape sequences will under no circumstances be encoded or decoded automatically. The class CIni provides auxiliary methods for encoding or decoding string values.
Comments are introduced by a semicolon character. Comments terminate at the end of the line. The parser will treat an end of file like an end of line. To prevail the structure of a given INI file empty lines are read as comment lines assigned the value null.
Whitespace includes space (hexadecimal code 20), horizontal tab (9), line feed (A), carriage return (D), vertical tab (B), and form feed (C).
On Microsoft Windows operating systems both a line feed or a carriage return followed by a line feed terminate a line.
Text may be encoded using any encoding of the .NET System.Text.Encoding class (ASCII, Unicode, UTF-7, UTF-8, "Latin1" etc.). Default encoding is UTF-8.
Double quotation marks appearing inside of a value enclosed in double quotation marks must be encoded as an escape sequence, containing the double quotation mark followed by a backslash: \". All other characters are valid characters which needn't be encoded. Inside of values not enclosed in double quotation marks no characters need to be encoded (except comma and semicolon which aren't allowed); double quotation marks must be encoded only when occurring at the beginning of a value.
Thus the following two values are virtually the same (after decoding):
Key1="\"example value\"" ; After decoding it becomes: "example value"
Key2=\"example value" ; After decoding it becomes: "example value"
The following example uses INI classes to create a new INI file.
using System.Collections;
using Planet.Utility.Ini; // Namespace of INI file format implementation
// Create a new INI file, set encoding to "Latin1".
CIni Ini = new CIni("Aquineo.ini",
System.Text.Encoding.GetEncoding("Latin1"));
// Add a section with comment lines, inline comments,
// key/value pairs etc.
ArrayList CommentLines = new ArrayList();
CommentLines.Add("------------------------------------");
CommentLines.Add("Aquineo Software");
CommentLines.Add("Implementation of INI file format");
CommentLines.Add("------------------------------------");
Ini.AddSection("LibraryInfo", CommentLines);
Ini.GetSection("LibraryInfo").Comment = "General information on program";
// Add key and value for "Version".
Ini.GetSection("LibraryInfo").AddKey("Version", null);
Ini.GetSection("LibraryInfo").GetKey("Version").
AddValue(new CIniValueItem("1.0.1"));
// Add key and value for "Licence" in one step.
Ini.SetValue("LibraryInfo", "Licence", "Open source", false);
// Add key and value for "Release" in one step.
Ini.SetValue("LibraryInfo", "Release", "2004-05-01", false);
// Add key for "Changes".
CommentLines = new ArrayList();
CommentLines.Add(null); // Empty line
CommentLines.Add("Changes (excluding bugfixes).");
Ini.GetSection("LibraryInfo").AddKey("Changes", CommentLines);
CIniKeyItem KeyChanges = Ini.GetSection("LibraryInfo").GetKey("Changes");
KeyChanges.AddValue(
new CIniValueItem("2004-05-09: CIni.TextEncoding made read only."));
KeyChanges.AddValue(
new CIniValueItem("2004-04-28: CIniValueItem.Value returns value " +
"as is, not necessarily adding CIniValueItem.QUOTE_DELIMITER " +
"char (\\\").", true));
// Finally save INI file.
Ini.Write();
This is what you should expect:
;------------------------------------
;Aquineo Software
;Implementation of INI file format
;------------------------------------
[LibraryInfo] ;General information on program
Version=1.0.1
Licence=Open source
Release=2004-05-01
;Changes (excluding bugfixes).
Changes=2004-05-09: CIni.TextEncoding made read only.,"2004-04-28:
CIniValueItem.Value returns value as is, not necessarily adding
CIniValueItem.QUOTE_DELIMITER char (\")."
This example loads the previously created INI file.
using Planet.Utility.Ini;
// Load an existing INI file, set encoding to "Latin1".
CIni Ini = new CIni("Aquineo.ini",
System.Text.Encoding.GetEncoding("Latin1"));
// Read value.
string LibVersion = Ini.GetValue("LibraryInfo", "Version", 0, false);
// Pass list of changes.
for (int i = 0; i < Ini.CountValues("LibraryInfo", "Changes"); ++i)
{
string Change = CIni.Unescape(
Ini.GetValue("LibraryInfo", "Changes", i, false));
// Do something with Change...
}
Aquineo disclaims all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall Aquineo be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software.
Permission to use, copy, modify, and distribute this software for any purpose and without fee is hereby granted, subject to the following restrictions:
We would like to thank Cloanto for making available their specification
of INI file format:
http://www.cloanto.com/specs/ini.html.