[C#] INI 파일 읽기 / 쓰기

표준 .ini 파일을 읽고 쓸 수있는 클래스가 .NET 프레임 워크에 있습니까?

[Section]
<keyname>=<value>
...

델파이는 TIniFile구성 요소를 가지고 있으며 C #과 비슷한 것이 있는지 알고 싶습니다.



답변

.NET 프레임 워크 작성자는 INI 파일 대신 XML 기반 구성 파일을 사용하기를 원합니다. 그래서, 그것들을 읽을 수있는 내장 메커니즘이 없습니다.

그러나 사용 가능한 타사 솔루션이 있습니다.


답변

머리말

먼저 INI 파일의 제한 사항대한 이 MSDN 블로그 게시물을 읽으십시오 . 필요에 맞는 경우 계속 읽으십시오.

이것은 원본 Windows P / Invoke를 사용하여 작성한 간결한 구현이므로 .NET이 설치된 모든 Windows 버전 (예 : Windows 98-Windows 10)에서 지원됩니다. 본인은이를 공개 도메인으로 공개합니다. 귀하는 저작자 표시없이 상업적으로 자유롭게 사용할 수 있습니다.

작은 수업

IniFile.cs프로젝트에 호출 된 새 클래스를 추가하십시오 .

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;
        }
    }
}

사용 방법

다음 3 가지 방법 중 하나로 INI 파일을 엽니 다.

// 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");

다음과 같은 값을 쓸 수 있습니다.

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

다음과 같은 파일을 만들려면

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

INI 파일에서 값을 읽으려면 :

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

선택적으로의를 설정할 수 있습니다 [Section].

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

다음과 같은 파일을 만들려면

[Audio]
DefaultVolume=100

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

다음과 같이 키가 있는지 확인할 수도 있습니다.

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

다음과 같이 키를 삭제할 수 있습니다.

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

다음과 같이 전체 섹션 (모든 키 포함)을 삭제할 수도 있습니다.

MyIni.DeleteSection("Web");

개선 사항이 있으면 언제든지 의견을 남겨주세요!


답변

CodeProject에 대한이 기사 ” C #을 사용한 INI 파일 처리 클래스 “가 도움이 될 것입니다.

작성자는 KERNEL32.dll에서 두 가지 기능을 제공하는 C # 클래스 “Ini”를 만들었습니다. 이러한 기능은 다음 WritePrivateProfileString과 같습니다 GetPrivateProfileString. 두 개의 네임 스페이스가 필요합니다 : System.Runtime.InteropServicesSystem.Text.

Ini 클래스를 사용하는 단계

프로젝트 네임 스페이스 정의에 추가

using INI;

이와 같은 INIFile을 만듭니다.

INIFile ini = new INIFile("C:\\test.ini");

사용 IniWriteValue섹션 또는 사용의 특정 키에 새 값을 작성하는 IniReadValue특정 섹션의 키에서 값을 읽을 수 있습니다.

참고 : 처음부터 시작하는 경우이 MSDN 문서 : 방법 : C # 프로젝트에 응용 프로그램 구성 파일 추가를 읽을 수 있습니다. 응용 프로그램을 구성하는 더 좋은 방법입니다.


답변

이 간단한 구현을 찾았습니다.

http://bytes.com/topic/net/insights/797169-reading-parsing-ini-file-c

내가 필요한 것에 잘 작동합니다.

사용 방법은 다음과 같습니다.

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();
    }
}

코드는 다음과 같습니다.

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);
    }
}


답변

joerage의 답변에있는 코드는 고무적입니다.

불행히도 키의 문자 대소 문자를 변경하고 주석을 처리하지 않습니다. 그래서 매우 더러운 INI 파일을 읽을 수있을 정도로 강력해야하며 키를 그대로 가져올 수있는 무언가를 작성했습니다.

섹션, 키 및 값을 저장하고 한 번에 파일을 읽기 위해 대소 문자를 구분하지 않는 중첩 된 문자열 사전 인 LINQ를 사용합니다.

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();
    }
}


답변

c #에서 완전히 만든 IniParser 라이브러리를 소개하고 싶습니다. 따라서 모든 OS에 종속성이 없으므로 Mono와 호환됩니다. MIT 라이센스가있는 오픈 소스이므로 모든 코드에서 사용할 수 있습니다.

당신은 할 수 GitHub의에서 소스를 체크 아웃 하고는 NuGet 패키지로도 제공

그건 크게 구성사용에 정말 간단 .

뻔뻔스런 플러그에 대해 죄송하지만이 답변을 다시 방문하는 사람에게 도움이되기를 바랍니다.


답변

읽기 액세스 만 필요하고 쓰기 액세스는 필요하지 않고 Microsoft.Extensions.ConfiurationASP.NET Core에 기본적으로 번들로 제공되지만 일반 프로그램에서도 작동합니다)를 사용하는 경우 NuGet 패키지 Microsoft.Extensions.Configuration.Ini를 사용하여 ini 파일을 구성 설정으로 가져올 수 있습니다.

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddIniFile("SomeConfig.ini", optional: false);
    Configuration = builder.Build();
}