-1

我想使用此代码将一些设置写入ini文件,以搜索查找密钥并更新它,如果找不到密钥将其添加到文件中。但它显示此错误:“对象引用未设置为对象的实例。” 我试试这个代码:

    internal class IniData
    {
        public string Key;
        public string Value;
    }

    internal class IniSection : Dictionary<string, IniData>
    {
        public string Name { get; set; }
    }

    internal class IniFile : Dictionary<string, IniSection>
    {
        public string Path { get; set; }
    }

    public sealed class IniManager
    {
        private static readonly Dictionary<string, IniFile> IniFiles;
        static IniManager()
        {
            IniFiles = new Dictionary<string, IniFile>();
        }

        public static void WriteIni(string fileName, string section, string key, string value)
        {
            /* Check if ini file exists in the ini collection */
            var fileKey = fileName.ToLower();
            if (!IniFiles.ContainsKey(fileKey))
            {
                if (!ImportIni(fileKey))
                {
                    /* Add a new blank file */
                    var ini = new IniFile { Path = fileName };
                    IniFiles.Add(fileKey, ini);
                }
            }
            /* Find section */
            if (IniFiles[fileKey].ContainsKey(section.ToLower()))
            {
                /* Find key, if exists replace it */
                if (IniFiles[fileKey][section.ToLower()].ContainsKey(key.ToLower()))
                {
                    IniFiles[fileKey][section.ToLower()][key.ToLower()].Value = value;
                    return;
                }
                var data = new IniData { Key = key, Value = value };
                IniFiles[fileKey][section.ToLower()].Add(key.ToLower(), data);
            }
            else
            {
                /* Create new ini section */
                var sec = new IniSection { Name = section };
                var data = new IniData { Key = key, Value = value };
                sec.Add(key.ToLower(), data);
                IniFiles[fileKey].Add(section.ToLower(), sec);
            }
        }
        private static bool ImportIni(string fileName)
        {
            if (!File.Exists(fileName)) { return false; }
            string[] data;
            try
            {
                using (var stream = new FileStream(fileName, FileMode.Open))
                {
                    using (var reader = new StreamReader(stream))
                    {
                        data = reader.ReadToEnd().Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                        reader.Close();
                    }
                    stream.Close();
                }
            }
            catch (Exception) { return false; }
            if (data.Length == 0) { return false; }
            var file = new IniFile { Path = fileName };
            var section = new IniSection();
            foreach (var s in data)
            {
                if (s.StartsWith("[") && s.EndsWith("]"))
                {
                    /* Section header */
                    if (section.Count > 0)
                    {
                        /* Add current section */
                        file.Add(section.Name.ToLower(), section);
                    }
                    section = new IniSection { Name = s.Replace("[", null).Replace("]", null) };
                    continue;
                }
                /* Using current section, parse ini keys/values */
                var iniData = ParseIni(s);
                section.Add(iniData.Key.ToLower(), iniData);
            }
            if (section.Count > 0)
            {
                /* Add current section */
  //@@@@@@@@@@@@@@@@@@Erorr : Object reference not set to an instance of an object.
                file.Add(section.Name.ToLower(), section);
            }
            IniFiles.Add(fileName, file);
            return true;
        }
        private static IniData ParseIni(string s)
        {
            var parts = s.Split('=');
            return new IniData { Key = parts[0].Trim(), Value = parts.Length > 1 ? parts[1].Trim() : string.Empty };
        }
    }
    private void button9_Click(object sender, EventArgs e)
    {
        IniManager.WriteIni("seting.ini", "Sec", "key", "value");

    }
4

2 回答 2

1

与其自己实现,不如只使用 Windows 提供的 API 函数。当然,如果您需要在 Mono 或 Windows 以外的其他平台上运行它,您需要回到纯 .NET 实现,但即便如此,我可能会去寻找现有的实现,而不是自己创建那个轮子。

任何地方,这里的 API 函数:

这是一个使用它们的示例LINQPad程序:

(按 F4 并将以下两行粘贴到附加命名空间选项卡中):

System.Runtime.InteropServices
System.ComponentModel

然后试试这个程序:

void Main()
{
    var ini = new IniFile(@"d:\temp\test.ini");
    ini.WriteValue("Section", "Key", "Value");
    ini.ReadValue("Section", "Key").Dump();

    ini["Main", "Key2"] = "Test";
    ini["Main", "Key2"].Dump();
}

[DllImport("kernel32.dll", CharSet=CharSet.Unicode)]
static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName,string lpDefault, StringBuilder lpReturnedString, uint nSize,string lpFileName);

[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);

public class IniFile
{
    const int MAX_SIZE = 1024;

    private readonly string _FilePath;

    public IniFile(string filePath)
    {
        if (filePath == null)
            throw new ArgumentNullException("filePath");

        _FilePath = filePath;
    }

    public string this[string section, string key]
    {
        get
        {
            return ReadValue(section, key);
        }

        set
        {
            WriteValue(section, key, value);
        }
    }

    public string ReadValue(string section, string key, string defaultValue = null)
    {
        var result = new StringBuilder(MAX_SIZE);
        if (GetPrivateProfileString(section, key, defaultValue ?? string.Empty, result, (uint)result.Capacity, _FilePath) > 0)
            return result.ToString();

        throw new Win32Exception();
    }

    public void WriteValue(string section, string key, string value)
    {
        if (!WritePrivateProfileString(section, key, value, _FilePath))
            throw new Win32Exception();
    }
}
于 2013-08-02T12:02:13.117 回答
0

这里的问题是,如果文件以键而不是节开头,则foreach根本不匹配if (s.StartsWith("[") && s.EndsWith("]")),因此Section.Name永远不会设置,因此null在调用时file.Add(section.Name.ToLower(), section);

顺便说一句:您的代码似乎有很多错误,请尝试至少在主要foreach方面重新设计它ImportIni

于 2013-08-02T11:40:41.453 回答