using System; using System.Collections.Generic; using System.IO; //Example: // var c = new ConfigFile("default.txt", Properties.Resources._default); // var x = c.Get("some keyword"); // class ConfigFile { const string DELIMITER = "="; const string COMMENT_CHAR_1 = ";"; const string COMMENT_CHAR_2 = "#"; private Dictionary<string, string> _dictionary = null; private List<string> _flatlist = null; private string _primaryFile; private byte[] _resource; // Assumes the factory-settings config file is stored as a resource in the project public ConfigFile(string primaryFilename, byte[] resource) { _primaryFile = primaryFilename; _resource = resource; } public static string MakeBase(string filename) { return filename + ".base"; } private static bool StartsWithCommentChar(string s) { return (s.StartsWith(COMMENT_CHAR_1) || s.StartsWith(COMMENT_CHAR_2)); } private static void ReadFileIntoDictionary(string filename, out Dictionary<string, string> dictionary, out List<string> flatList) { dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); flatList = new List<string>(); using (TextReader sr = new StreamReader(filename)) { string input; while ((input = sr.ReadLine()) != null) { // If it starts with a comment character, then skip, otherwise // split the string into two parts, separated by an equal sign. if (StartsWithCommentChar(input)) { flatList.Add(input); } else if (input.Contains(DELIMITER)) { string[] parts = input.Split(new char[] { DELIMITER[0] }, 2); if (parts.Length != 2) throw new Exception("bad code"); dictionary[parts[0]] = parts[1]; flatList.Add(parts[0]); } } } } private void CreatePrimaryConfigFile(out Dictionary<string, string> d, out List<string> l) { File.WriteAllBytes(_primaryFile, _resource); File.WriteAllBytes(MakeBase(_primaryFile), _resource); ReadFileIntoDictionary(_primaryFile, out d, out l); } // Only add entries if they are new keys, or for existing keys, the base and current haven't changed. private static bool AddNewEntries(Dictionary<string, string> primaryDiskDictionary, Dictionary<string, string> resDictionary, Dictionary<string, string> baseDiskDictionary) { bool anEntryWasAdded = false; foreach (var item in resDictionary) { bool doAdd = false; // If the key doesn't exist in the current, then add it. if (!primaryDiskDictionary.ContainsKey(item.Key)) { doAdd = true; } else if (baseDiskDictionary.ContainsKey(item.Key)) { // If the base and the current are the same, then we can accept the new version. if (primaryDiskDictionary[item.Key] == baseDiskDictionary[item.Key] && primaryDiskDictionary[item.Key] == item.Value) { doAdd = true; } } if (doAdd) { primaryDiskDictionary[item.Key] = item.Value; anEntryWasAdded = true; } } return anEntryWasAdded; } private static void CreateConfigurationFile(string filename, List<string> flatList, Dictionary<string, string> dictionary) { using (TextWriter stream = new StreamWriter(filename)) { foreach (var item in flatList) { if (StartsWithCommentChar(item)) stream.WriteLine(item); else stream.WriteLine("{0}{1}{2}", item, DELIMITER, dictionary[item]); } } } private void MergeConfigFile(out Dictionary<string, string> primaryDiskDictionary, out List<string> resList) { // Add new entries from the resource to the disk file. // Load the "current" version from disk List<string> primaryDiskList; ReadFileIntoDictionary(_primaryFile, out primaryDiskDictionary, out primaryDiskList); // Load the "base" version from disk // If the base file isn't there for some reason, create it by copying the primary one. if (!File.Exists(MakeBase(_primaryFile))) File.Copy(_primaryFile, MakeBase(_primaryFile), false); Dictionary<string, string> baseDiskDictionary; List<string> baseDiskList; ReadFileIntoDictionary(MakeBase(_primaryFile), out baseDiskDictionary, out baseDiskList); // Load the one from Resources. var tempPathResVersion = Path.GetTempFileName(); try { File.WriteAllBytes(tempPathResVersion, _resource); Dictionary<string, string> resDictionary; ReadFileIntoDictionary(tempPathResVersion, out resDictionary, out resList); // Add new entries, and write dictionary to file if necessary. // Only add entries if they are new keys. Or for existing keys, the base and primary haven't changed. if (AddNewEntries(primaryDiskDictionary, resDictionary, baseDiskDictionary)) CreateConfigurationFile(_primaryFile, resList, primaryDiskDictionary); } finally { File.Delete(tempPathResVersion); } } private void LoadDictionaryFromPrimaryFile(out Dictionary<string, string> primaryDiskDictionary, out List<string> list) { // If the file is already there, add new entries from the resource to the file, otherwise start the new file as // clone of the resource. if (File.Exists(_primaryFile)) MergeConfigFile(out primaryDiskDictionary, out list); else CreatePrimaryConfigFile(out primaryDiskDictionary, out list); } private void EnsureDictionaryLoaded() { if (_dictionary == null) LoadDictionaryFromPrimaryFile(out _dictionary, out _flatlist); } public string this[string key] { get { EnsureDictionaryLoaded(); return _dictionary[key]; } set { EnsureDictionaryLoaded(); _dictionary[key] = value; CreateConfigurationFile(_primaryFile, _flatlist, _dictionary); } } public void SaveAs(string newFilename) { // Write the primary settings to the new file. CreateConfigurationFile(newFilename, _flatlist, _dictionary); // Copy the base settings of the primary file. File.Copy(MakeBase(_primaryFile), MakeBase(newFilename), true); } public List<string> GetList(string fieldKey) { var list = new List<string>(); var listCount = int.Parse(this[fieldKey + " Count"]); for (int listIndex = 0; listIndex < listCount; listIndex++) list.Add(this[string.Format("{0} {1}", fieldKey, listIndex)]); return list; } }
Advertisement
160
pages
Read Unix type configuration files
Advertisement