This project is read-only.
1
Vote

Ini document, trailing spaces in the property names are part of the key

description

If you read the following ini file into an IniDocument:
 
[globalSettings]
key1 : value
key2 : another value
 
The space between the name "key1" and the colon (:) will be part of the key that is stored in the IniDocument.
 
So, if you try to retrieve the property value (note: no space after "key1"):
 
var value = inidocument["globalSettings", "key1"];
 
The value will be null because the property with key "key1" isn't found, it must be specified as "key1 ".
 
I don't know if this really is a bug. It can be a matter of definition. But in our case it was pretty annoying because we have ini files that are often modified by hand and, as a result, the use of spaces before and after the colon varied wildly.
 
It also contradicts with the IniDocument.Save() method that will save all the sections and properties to a new file but adds an extra space between the key and the colon (:), see method IniSection.ToString(). This results in a new ini file that is not the same as the original and can't be used anymore because all the keys now have a extra space in their name.
 
I've solved this by removing the trailing spaces of the property name before the key/value pair is stored in the section.
 
Patched IniParser.StoreKeyValue() in source file: trunk\src\Lib\CommonLibrary.NET\IO\IniDocument.cs
 
    protected virtual void StoreKeyValue()
    {
        string val = "";
        string key = _reader.ReadToken(':', '\\', false, false, true, true);
        key = key.TrimEnd();
 
        _reader.ConsumeWhiteSpace();
        // If starting with " then possibly multi-line.
        if (_reader.CurrentChar == '"')
            val = _reader.ReadToken('"', '\\', false, true, true, true);
        else
            val = _reader.ReadToEol();
 
        if (!_settings.IsCaseSensitive)
            key = key.ToLower();
 
        // This allow multiple values for the same key.
        // Multiple values are stored using List<object>.
        _currentSection.AddMulti(key, val, false);
        //_lastLineType = IniLineType.KeyValue;
    }
 
The following unit-test will verify the change:
[Test]
public void CanParseNamesWithTrailingSpaces()
{
string iniContent = "[globalSettings]" + Environment.NewLine
                    + "title:Learn painting" + Environment.NewLine
                    + "time : all" + Environment.NewLine
                    + "category    :  Art,Drawing";
 
IniDocument document = new IniDocument(iniContent, false);
 
Assert.IsTrue(document.Contains("globalSettings"));
Assert.AreEqual(document["globalSettings", "title"], "Learn painting");
Assert.AreEqual(document["globalSettings", "time"], "all");
Assert.AreEqual(document["globalSettings", "category"], "Art,Drawing");
}

comments