Thursday, June 02, 2016

Parsing INI files

I am trying to allow the end user to modify the application behavior in some limited ways; as such, I have a need of parsing .INI files of the form

[Type 1]

[Type 2]

I looked around for a class / library that would allow me to read these files but I haven't found anything useful (most of the classes I found couldn't handle duplicate keys within the same section). As such, I went ahead and implemented this myself. This algorithm is extremely specific to my usage, you might have to modify it for your needs.

The IniTuple represents each line as a (section, key, value) tuple:

    public class IniTuple
        public string Section { get; private set; }
        public string Key { get; private set; }
        public string Value { get; private set; }

        public IniTuple(string section, string key, string value)
            Section = section;
            Key = key;
            Value = value;

The IniParser class implements the algorithm that transforms a string to a list of IniTuples:

    public class IniParser
        public IEnumerable<IniTuple> Read(string text)
            var lines = text
                .Split('\r', '\n')
                .Where(line => !string.IsNullOrWhiteSpace(line))

            var section = "";
            foreach (var line in lines)
                if (IsNewSection(line))
                    section = line.Substring(1, line.Length - 2);
                    yield return GetTuple(section, line);


        private static string RemoveComment(string line)
            var index = line.IndexOf(';');
            return index < 0 ? line : line.Substring(0, index);

        private static bool IsNewSection(string line)
            return Regex.IsMatch(line, @"^\s*\[[^]]+\]\s*$");

        private static IniTuple GetTuple(string section, string line)
            var index = line.IndexOf('=');
            return index < 0
                ? new IniTuple(section, "", line)
                : new IniTuple(section, line.Substring(0, index), line.Substring(index + 1));

Please let me know if this was useful. As usual, I don't believe in copyrights so feel free to do whatever you want with the code.

No comments: