Reading/writing an INI file

后端 未结 16 2395
南旧
南旧 2020-11-22 00:15

Is there any class in the .NET framework that can read/write standard .ini files:

[Section]
=
...

Delphi has th

相关标签:
16条回答
  • 2020-11-22 00:46

    Preface

    Firstly, read this MSDN blog post on the limitations of INI files. If it suits your needs, read on.

    This is a concise implementation I wrote, utilising the original Windows P/Invoke, so it is supported by all versions of Windows with .NET installed, (i.e. Windows 98 - Windows 10). I hereby release it into the public domain - you're free to use it commercially without attribution.

    The tiny class

    Add a new class called IniFile.cs to your project:

    using System.IO;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Text;
    
    // Change this to match your program's normal namespace
    namespace MyProg
    {
        class IniFile   // revision 11
        {
            string Path;
            string EXE = Assembly.GetExecutingAssembly().GetName().Name;
    
            [DllImport("kernel32", CharSet = CharSet.Unicode)]
            static extern long WritePrivateProfileString(string Section, string Key, string Value, string FilePath);
    
            [DllImport("kernel32", CharSet = CharSet.Unicode)]
            static extern int GetPrivateProfileString(string Section, string Key, string Default, StringBuilder RetVal, int Size, string FilePath);
    
            public IniFile(string IniPath = null)
            {
                Path = new FileInfo(IniPath ?? EXE + ".ini").FullName;
            }
    
            public string Read(string Key, string Section = null)
            {
                var RetVal = new StringBuilder(255);
                GetPrivateProfileString(Section ?? EXE, Key, "", RetVal, 255, Path);
                return RetVal.ToString();
            }
    
            public void Write(string Key, string Value, string Section = null)
            {
                WritePrivateProfileString(Section ?? EXE, Key, Value, Path);
            }
    
            public void DeleteKey(string Key, string Section = null)
            {
                Write(Key, null, Section ?? EXE);
            }
    
            public void DeleteSection(string Section = null)
            {
                Write(null, null, Section ?? EXE);
            }
    
            public bool KeyExists(string Key, string Section = null)
            {
                return Read(Key, Section).Length > 0;
            }
        }
    }
    

    How to use it

    Open the INI file in one of the 3 following ways:

    // Creates or loads an INI file in the same directory as your executable
    // named EXE.ini (where EXE is the name of your executable)
    var MyIni = new IniFile();
    
    // Or specify a specific name in the current dir
    var MyIni = new IniFile("Settings.ini");
    
    // Or specify a specific name in a specific dir
    var MyIni = new IniFile(@"C:\Settings.ini");
    

    You can write some values like so:

    MyIni.Write("DefaultVolume", "100");
    MyIni.Write("HomePage", "http://www.google.com");
    

    To create a file like this:

    [MyProg]
    DefaultVolume=100
    HomePage=http://www.google.com
    

    To read the values out of the INI file:

    var DefaultVolume = MyIni.Read("DefaultVolume");
    var HomePage = MyIni.Read("HomePage");
    

    Optionally, you can set [Section]'s:

    MyIni.Write("DefaultVolume", "100", "Audio");
    MyIni.Write("HomePage", "http://www.google.com", "Web");
    

    To create a file like this:

    [Audio]
    DefaultVolume=100
    
    [Web]
    HomePage=http://www.google.com
    

    You can also check for the existence of a key like so:

    if(!MyIni.KeyExists("DefaultVolume", "Audio"))
    {
        MyIni.Write("DefaultVolume", "100", "Audio");
    }
    

    You can delete a key like so:

    MyIni.DeleteKey("DefaultVolume", "Audio");
    

    You can also delete a whole section (including all keys) like so:

    MyIni.DeleteSection("Web");
    

    Please feel free to comment with any improvements!

    0 讨论(0)
  • 2020-11-22 00:46

    Try this method:

    public static Dictionary<string, string> ParseIniDataWithSections(string[] iniData)
    {
        var dict = new Dictionary<string, string>();
        var rows = iniData.Where(t => 
            !String.IsNullOrEmpty(t.Trim()) && !t.StartsWith(";") && (t.Contains('[') || t.Contains('=')));
        if (rows == null || rows.Count() == 0) return dict;
        string section = "";
        foreach (string row in rows)
        {
            string rw = row.TrimStart();
            if (rw.StartsWith("["))
                section = rw.TrimStart('[').TrimEnd(']');
            else
            {
                int index = rw.IndexOf('=');
                dict[section + "-" + rw.Substring(0, index).Trim()] = rw.Substring(index+1).Trim().Trim('"');
            }
        }
        return dict;
    }
    

    It creates the dictionary where the key is "-". You can load it like this:

    var dict = ParseIniDataWithSections(File.ReadAllLines(fileName));
    
    0 讨论(0)
  • 2020-11-22 00:46

    Here is my class, works like a charm :

    public static class IniFileManager
    {
    
    
        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section,
            string key, string val, string filePath);
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section,
                 string key, string def, StringBuilder retVal,
            int size, string filePath);
        [DllImport("kernel32.dll")]
        private static extern int GetPrivateProfileSection(string lpAppName,
                 byte[] lpszReturnBuffer, int nSize, string lpFileName);
    
    
        /// <summary>
        /// Write Data to the INI File
        /// </summary>
        /// <PARAM name="Section"></PARAM>
        /// Section name
        /// <PARAM name="Key"></PARAM>
        /// Key Name
        /// <PARAM name="Value"></PARAM>
        /// Value Name
        public static void IniWriteValue(string sPath,string Section, string Key, string Value)
        {
            WritePrivateProfileString(Section, Key, Value, sPath);
        }
    
        /// <summary>
        /// Read Data Value From the Ini File
        /// </summary>
        /// <PARAM name="Section"></PARAM>
        /// <PARAM name="Key"></PARAM>
        /// <PARAM name="Path"></PARAM>
        /// <returns></returns>
        public static string IniReadValue(string sPath,string Section, string Key)
        {
            StringBuilder temp = new StringBuilder(255);
            int i = GetPrivateProfileString(Section, Key, "", temp,
                                            255, sPath);
            return temp.ToString();
    
        }
    

    }

    The use is obviouse since its a static class, just call IniFileManager.IniWriteValue for readsing a section or IniFileManager.IniReadValue for reading a section.

    0 讨论(0)
  • 2020-11-22 00:48

    If you want just a simple reader without sections and any other dlls here is simple solution:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Tool
    {
        public class Config
        {
            Dictionary <string, string> values;
            public Config (string path)
            {
                values = File.ReadLines(path)
                .Where(line => (!String.IsNullOrWhiteSpace(line) && !line.StartsWith("#")))
                .Select(line => line.Split(new char[] { '=' }, 2, 0))
                .ToDictionary(parts => parts[0].Trim(), parts => parts.Length>1?parts[1].Trim():null);
            }
            public string Value (string name, string value=null)
            {
                if (values!=null && values.ContainsKey(name))
                {
                    return values[name];
                }
                return value;
            }
        }
    }
    

    Usage sample:

        file = new Tool.Config (Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\config.ini");
        command = file.Value ("command");
        action = file.Value ("action");
        string value;
        //second parameter is default value if no key found with this name
        value = file.Value("debug","true");
        this.debug = (value.ToLower()=="true" || value== "1");
        value = file.Value("plain", "false");
        this.plain = (value.ToLower() == "true" || value == "1");
    

    Config file content meanwhile (as you see supports # symbol for line comment):

    #command to run
    command = php
    
    #default script
    action = index.php
    
    #debug mode
    #debug = true
    
    #plain text mode
    #plain = false
    
    #icon = favico.ico
    
    0 讨论(0)
  • 2020-11-22 00:49

    If you only need read access and not write access and you are using the Microsoft.Extensions.Confiuration (comes bundled in by default with ASP.NET Core but works with regular programs too) you can use the NuGet package Microsoft.Extensions.Configuration.Ini to import ini files in to your configuration settings.

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddIniFile("SomeConfig.ini", optional: false);
        Configuration = builder.Build();
    }
    
    0 讨论(0)
  • 2020-11-22 00:52

    The code in joerage's answer is inspiring.

    Unfortunately, it changes the character casing of the keys and does not handle comments. So I wrote something that should be robust enough to read (only) very dirty INI files and allows to retrieve keys as they are.

    It uses some LINQ, a nested case insensitive string dictionary to store sections, keys and values, and read the file in one go.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    
    class IniReader
    {
        Dictionary<string, Dictionary<string, string>> ini = new Dictionary<string, Dictionary<string, string>>(StringComparer.InvariantCultureIgnoreCase);
    
        public IniReader(string file)
        {
            var txt = File.ReadAllText(file);
    
            Dictionary<string, string> currentSection = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
    
            ini[""] = currentSection;
    
            foreach(var line in txt.Split(new[]{"\n"}, StringSplitOptions.RemoveEmptyEntries)
                                   .Where(t => !string.IsNullOrWhiteSpace(t))
                                   .Select(t => t.Trim()))
            {
                if (line.StartsWith(";"))
                    continue;
    
                if (line.StartsWith("[") && line.EndsWith("]"))
                {
                    currentSection = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
                    ini[line.Substring(1, line.LastIndexOf("]") - 1)] = currentSection;
                    continue;
                }
    
                var idx = line.IndexOf("=");
                if (idx == -1)
                    currentSection[line] = "";
                else
                    currentSection[line.Substring(0, idx)] = line.Substring(idx + 1);
            }
        }
    
        public string GetValue(string key)
        {
            return GetValue(key, "", "");
        }
    
        public string GetValue(string key, string section)
        {
            return GetValue(key, section, "");
        }
    
        public string GetValue(string key, string section, string @default)
        {
            if (!ini.ContainsKey(section))
                return @default;
    
            if (!ini[section].ContainsKey(key))
                return @default;
    
            return ini[section][key];
        }
    
        public string[] GetKeys(string section)
        {
            if (!ini.ContainsKey(section))
                return new string[0];
    
            return ini[section].Keys.ToArray();
        }
    
        public string[] GetSections()
        {
            return ini.Keys.Where(t => t != "").ToArray();
        }
    }
    
    0 讨论(0)
提交回复
热议问题