2013-08-02 29 views
-1

我想使用此代碼編寫一些設置來搜索找到密鑰並更新它,如果找不到密鑰將它添加到文件。但它表明這個錯誤: 「不設置到對象的實例對象引用。」 我試試這個代碼:寫入並更新ini文件的密鑰c#

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

    } 
+0

會發生這種情況在哪一行? – christopher

+1

上有SO千萬的問題有關'NullReferenceException'。請閱讀它們,嘗試瞭解發生了什麼,調試程序並自己找到答案。提示:它是關於'Section.Name'。 – CodeCaster

+0

使用INI文件似乎有點老套。 – James

回答

0

這裏的問題是,如果文件一鍵啓動,而不是用的區段,該foreach不匹配if (s.StartsWith("[") && s.EndsWith("]"))所有等等Section.Name從未設置,從而它是nullfile.Add(section.Name.ToLower(), section);

BTW調用時:你的代碼看起來很越野車,試圖在主foreachImportIni

1

至少重新設計,而不是實施這種yoursel你應該只使用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(); 
    } 
}