Reading and parsing an INI file in C#

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • ShadowLocke
    New Member
    • Jan 2008
    • 116

    Reading and parsing an INI file in C#

    This class makes use of System.Collecti ons.Hashtable to enumerate all the settings in an INI file for easy access. Its very simplistic, and completely re-useable. Solid addition for any app that requires a settings file.

    Code:
    using System;
    using System.IO;
    using System.Collections;
    
    public class IniParser
    {
        private Hashtable keyPairs = new Hashtable();
        private String iniFilePath;
    
        private struct SectionPair
        {
            public String Section;
            public String Key;
        }
    
        /// <summary>
        /// Opens the INI file at the given path and enumerates the values in the IniParser.
        /// </summary>
        /// <param name="iniPath">Full path to INI file.</param>
        public IniParser(String iniPath)
        {
            TextReader iniFile = null;
            String strLine = null;
            String currentRoot = null;
            String[] keyPair = null;
    
            iniFilePath = iniPath;
    
            if (File.Exists(iniPath))
            {
                try
                {
                    iniFile = new StreamReader(iniPath);
    
                    strLine = iniFile.ReadLine();
    
                    while (strLine != null)
                    {
                        strLine = strLine.Trim().ToUpper();
    
                        if (strLine != "")
                        {
                            if (strLine.StartsWith("[") && strLine.EndsWith("]"))
                            {
                                currentRoot = strLine.Substring(1, strLine.Length - 2);
                            }
                            else
                            {
                                keyPair = strLine.Split(new char[] { '=' }, 2);
    
                                SectionPair sectionPair;
                                String value = null;
    
                                if (currentRoot == null)
                                    currentRoot = "ROOT";
    
                                sectionPair.Section = currentRoot;
                                sectionPair.Key = keyPair[0];
    
                                if (keyPair.Length > 1)
                                    value = keyPair[1];
    
                                keyPairs.Add(sectionPair, value);
                            }
                        }
    
                        strLine = iniFile.ReadLine();
                    }
    
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if (iniFile != null)
                        iniFile.Close();
                }
            }
            else
                throw new FileNotFoundException("Unable to locate " + iniPath);
    
        }
    
        /// <summary>
        /// Returns the value for the given section, key pair.
        /// </summary>
        /// <param name="sectionName">Section name.</param>
        /// <param name="settingName">Key name.</param>
        public String GetSetting(String sectionName, String settingName)
        {
            SectionPair sectionPair;
            sectionPair.Section = sectionName.ToUpper();
            sectionPair.Key = settingName.ToUpper();
    
            return (String)keyPairs[sectionPair];
        }
    
        /// <summary>
        /// Enumerates all lines for given section.
        /// </summary>
        /// <param name="sectionName">Section to enum.</param>
        public String[] EnumSection(String sectionName)
        {
            ArrayList tmpArray = new ArrayList();
    
            foreach (SectionPair pair in keyPairs.Keys)
            {
                if (pair.Section == sectionName.ToUpper())
                    tmpArray.Add(pair.Key);
            }
    
            return (String[])tmpArray.ToArray(typeof(String));
        }
    
        /// <summary>
        /// Adds or replaces a setting to the table to be saved.
        /// </summary>
        /// <param name="sectionName">Section to add under.</param>
        /// <param name="settingName">Key name to add.</param>
        /// <param name="settingValue">Value of key.</param>
        public void AddSetting(String sectionName, String settingName, String settingValue)
        {
            SectionPair sectionPair;
            sectionPair.Section = sectionName.ToUpper();
            sectionPair.Key = settingName.ToUpper();
    
            if (keyPairs.ContainsKey(sectionPair))
                keyPairs.Remove(sectionPair);
    
            keyPairs.Add(sectionPair, settingValue);
        }
    
        /// <summary>
        /// Adds or replaces a setting to the table to be saved with a null value.
        /// </summary>
        /// <param name="sectionName">Section to add under.</param>
        /// <param name="settingName">Key name to add.</param>
        public void AddSetting(String sectionName, String settingName)
        {
            AddSetting(sectionName, settingName, null);
        }
    
        /// <summary>
        /// Remove a setting.
        /// </summary>
        /// <param name="sectionName">Section to add under.</param>
        /// <param name="settingName">Key name to add.</param>
        public void DeleteSetting(String sectionName, String settingName)
        {
            SectionPair sectionPair;
            sectionPair.Section = sectionName.ToUpper();
            sectionPair.Key = settingName.ToUpper();
    
            if (keyPairs.ContainsKey(sectionPair))
                keyPairs.Remove(sectionPair);
        }
    
        /// <summary>
        /// Save settings to new file.
        /// </summary>
        /// <param name="newFilePath">New file path.</param>
        public void SaveSettings(String newFilePath)
        {
            ArrayList sections = new ArrayList();
            String tmpValue = "";
            String strToSave = "";
    
            foreach (SectionPair sectionPair in keyPairs.Keys)
            {
                if (!sections.Contains(sectionPair.Section))
                    sections.Add(sectionPair.Section);
            }
    
            foreach (String section in sections)
            {
                strToSave += ("[" + section + "]\r\n");
    
                foreach (SectionPair sectionPair in keyPairs.Keys)
                {
                    if (sectionPair.Section == section)
                    {
                        tmpValue = (String)keyPairs[sectionPair];
    
                        if (tmpValue != null)
                            tmpValue = "=" + tmpValue;
    
                        strToSave += (sectionPair.Key + tmpValue + "\r\n");
                    }
                }
    
                strToSave += "\r\n";
            }
    
            try
            {
                TextWriter tw = new StreamWriter(newFilePath);
                tw.Write(strToSave);
                tw.Close();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    
        /// <summary>
        /// Save settings back to ini file.
        /// </summary>
        public void SaveSettings()
        {
            SaveSettings(iniFilePath);
        }
    }
    Example of usage:

    INI File (C:\test.ini):

    Code:
    [AppSettings]
    msgPart1=Hello
    msgPart2= World
    
    [Punctuation]
    ex=!
    TestApp:

    Code:
    public class TestParser
    {
        public static void Main()
        {
            IniParser parser = new IniParser(@"C:\test.ini");
    
            String newMessage;
    
            newMessage = parser.GetSetting("appsettings", "msgpart1");
            newMessage += parser.GetSetting("appsettings", "msgpart2");
            newMessage += parser.GetSetting("punctuation", "ex");
    
            //Returns "Hello World!"
            Console.WriteLine(newMessage);
            Console.ReadLine();
        }
    }
  • r035198x
    MVP
    • Sep 2006
    • 13225

    #2
    What about comments in the ini file?

    Comment

    • jamesjiao
      New Member
      • Jul 2009
      • 1

      #3
      If you look through the code - all you have to do is to add another conditional statement as shown here (modified sections in bold):
      Code:
      if (strLine.StartsWith("[") && strLine.EndsWith("]"))
      {
        currentRoot = strLine.Substring(1, strLine.Length - 2);
      }
      else
      {
        [B]if (strLine.StartsWith("'")) {
          // assuming comments start with the apostrophe
          // do nothing
        } else 
        {[/B]
          keyPair = strLine.Split(new char[] { '=' }, 2);
          SectionPair sectionPair;
          String value = null;
       
          if (currentRoot == null)
            currentRoot = "ROOT";
        
          sectionPair.Section = currentRoot;
          sectionPair.Key = keyPair[0];
        
          if (keyPair.Length > 1)
            value = keyPair[1];
        
          keyPairs.Add(sectionPair, value);
        [B]}[/B]
      }
      Last edited by Frinavale; Sep 20 '10, 08:18 PM. Reason: Added code tags and fixed indentation. In the future please post code in [code] ... [/code] tags.

      Comment

      • WernerCD
        New Member
        • Feb 2010
        • 1

        #4
        My kingdom for this parser in a class.cs file...

        I'm trying to get this wedged into a class file so I can use it in a few places, since I really do like the layout of it, but when I move it and put it into a namespace it just acts all wonky on me.

        Comment

        • invalidptr
          New Member
          • Dec 2014
          • 1

          #5
          FYI The whole thing will fail if you have a duplicate key pair. You may want to extend to handle that situation.

          Comment

          • nick1908
            New Member
            • May 2015
            • 1

            #6
            Here is an open source library http://www.multipetros.gr/public-pro...s/confing-dll/ for ini files read/write. It's very well documented and uses indexers (like a dictionary) to contact with the properties. I suggest to give a try!

            Comment

            Working...