0

我在选项文件中有两个函数 GetKey 和 SetKey。

我在 settings_file.txt 中设置了一个键,它看起来像:

text = hello其中text是键,然后 = 和hello是当前键的值。

现在我需要添加另外两个函数,第一个是 List 类型,它获取一个字符串并返回一个 List

还有一个获取 Key 和 List 的函数。

所以这是前两个函数都可以工作的 GetKey 和 SetKey:

/*----------------------------------------------------------------
 * Module Name  : OptionsFile
 * Description  : Saves and retrievs application options
 * Author       : Danny
 * Date         : 10/02/2010
 * Revision     : 1.00
 * --------------------------------------------------------------*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Configuration;


/*
 *  Introduction :
 * 
 *  This module helps in saving application options
 * 
 * 
 *  Typical file could look like this:
 *  user_color=Red
 *  time_left=30
 *  
 * 
 * 
 * 
 * 
 * */

namespace DannyGeneral
{
    class OptionsFile
    {
        /*----------------------------------------
         *   P R I V A T E     V A R I A B L E S 
         * ---------------------------------------*/


        /*---------------------------------
         *   P U B L I C   M E T H O D S 
         * -------------------------------*/
        string path_exe;
        string temp_settings_file;
        string temp_settings_dir;
        string Options_File;
        StreamWriter sw;
        StreamReader sr;

/*----------------------------------------------------------
 * Function     : OptionsFile
 * Description  : Constructor
 * Parameters   : file_name is the name of the file to use
 * Return       : none
 * --------------------------------------------------------*/
    public OptionsFile(string settings)
    {
        if (!File.Exists(settings))
        {
            if (!Directory.Exists(Path.GetDirectoryName(settings)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(settings));
            }
            File.Create(settings).Close();
        }
        path_exe = Path.GetDirectoryName(Application.LocalUserAppDataPath);
        Options_File = settings; 
    }

/*----------------------------------------------------------
 * Function     : GetKey
 * Description  : gets the value of the key.
 * Parameters   : key
 * Return       : value of the key if key exist, null if not exist
 * --------------------------------------------------------*/
    public string GetKey(string key)
    {

      //  string value_of_each_key;
        string key_of_each_line;
        string line;
        int index;
        string key_value;
        key_value = null;

        sr = new StreamReader(Options_File);
        while (null != (line = sr.ReadLine()))
        {


            index = line.IndexOf("=");


           //    value_of_each_key = line.Substring(index+1);



            if (index >= 1)
            {
                key_of_each_line = line.Substring(0, index);
                if (key_of_each_line == key)
                {
                    key_value = line.Substring(key.Length + 1);
                }

            }
            else
            {
            }


        }
        sr.Close();
        return key_value;
    }


/*----------------------------------------------------------
 * Function     : SetKey
 * Description  : sets a value to the specified key
 * Parameters   : key and a value
 * Return       : none
 * --------------------------------------------------------*/
    public void SetKey(string key , string value)
    {
        bool key_was_found_inside_the_loop;
        string value_of_each_key;
        string key_of_each_line ;
        string line;
        int index;
        key_was_found_inside_the_loop = false;

        temp_settings_file = "\\temp_settings_file.txt";
        temp_settings_dir = path_exe + @"\temp_settings";
        if (!Directory.Exists(temp_settings_dir))
        {
            Directory.CreateDirectory(temp_settings_dir);
        }

        sw = new StreamWriter(temp_settings_dir+temp_settings_file);
        sr = new StreamReader(Options_File);
        while (null != (line = sr.ReadLine()))
        {

            index = line.IndexOf("=");
            key_of_each_line = line.Substring(0, index);
            value_of_each_key = line.Substring( index + 1);
         //   key_value = line.Substring(0,value.Length);
            if (key_of_each_line == key)
            {
                sw.WriteLine(key + " = " + value);
                key_was_found_inside_the_loop = true;

            }
            else
            {
                sw.WriteLine(key_of_each_line+"="+value_of_each_key);
            }

        }

        if (!key_was_found_inside_the_loop)
        {
           sw.WriteLine(key + "=" + value);
        }
        sr.Close();
        sw.Close();
        File.Delete(Options_File);
        File.Move(temp_settings_dir + temp_settings_file, Options_File);
        return;

    }

在这两个功能之后,我做了:

public List<float> GetListFloatKey(string keys)
    {
        int j;
        List<float> t;
        t = new List<float>();
        int i;
        for (i = 0; ; i++)
        {
            j = Convert.ToInt32(GetKey((keys + i).ToString()));
            if (j == 0)
            {
                break;
            }
            else
            {
                t.Add(j);
            }
        }
        if (t.Count == 0)
            return null;
        else
            return t;
    }

    public void SetListFloatKey(string key, List<float> Values)
    {
        int i;
        for (i = 0; i < Values.Count; i++)
        {
            string indexed_key;
            indexed_key = string.Format("{0}{1}", key, i);
            //  indexed_key = Key + i.ToString();
            SetKey(indexed_key, Values[i].ToString());
        }
    }

但他们并不好。

最后一个 SetListFloatKey 当我将 List 放入其中时,文本文件 settings_file.txt 中的结果用于示例:

坐标01 = 123

坐标02 = 144

坐标03 = 145

对于列表中的每个单元格/索引,我都会得到它的密钥。我需要的是我得到的列表将有一个键,文本文件中的格式应该是这样的:

坐标= 123,144,145......等等一个键,然后我得到的列表中的所有值。

然后在 GetListFloatKey 中,我需要根据键重新格式化值,例如坐标,并返回一个列表,其索引值为 0 123 in 1 144 in 2 145 等等....

如果我在 GetKey 和 SetKey 中使用的功能在我做它们的方式上是好的?以及如何格式化和重新格式化这些值?

4

2 回答 2

0

目前,您正在为列表中的每个项目在 SetListFloatKey 中调用 SetKey。相反,您需要按照(已完成基本测试)构建一个字符串并调用它一次:

public static void SetListFloatKey(string key, List<float> Values)
{
  StringBuilder sb = new StringBuilder();
  foreach (float value in Values)
  {
    sb.AppendFormat("{0},", value);
  }
  SetKey(key, sb.ToString());
}

注意我在这里变得懒惰 - 最后一个项目后面会有一个逗号。然后在加载列表时:

public static List<float> GetListFloatKey(string keys)
{
  List<float> result = new List<float>();
  string s = GetKey(keys);
  string[] items = s.Split(new char[] { ',' });
  float f;
  foreach (string item in items)
  {
    if (float.TryParse(item, out f))
      result.Add(f);
  }
  return result;
}

但是,鉴于您正在读取和写入选项文件,您可能希望研究有关将对象序列化到文件和从文件中序列化的选项。

编辑有几种方法可以去掉多余的逗号。一种方法是一开始就不放它...

  string sep = "";
  foreach (float value in Values)
  {
    sb.AppendFormat("{0}{1}", sep, value);
    if (sep == "") sep = ",";
  }

...另一个是在调用 SetKey 时将其排除在外...

  foreach (float value in Values)
  {
    sb.AppendFormat(",{0}", value);
  }
  SetKey(key, sb.ToString().Substring(1));

..请注意,在这两种情况下,我都将逗号移到了开头,以使生活更轻松。或者,您可以将数字存储在数组中并使用 Array.Join。

于 2012-07-05T05:29:01.533 回答
0

我认为您在每次进行更改时都浪费了太多时间来考虑如何格式化文件,每次检查密钥时也会造成大量文件开销。

考虑使用类似的类

    public class Options
    {
        public static string FILENAME = @"C:\Test\testfile.txt";

        public List<KeyValuePair<string, string>> OrderedKeys { get; set; }
        public Dictionary<string, KeyValuePair<string, string>> Pairs { get; set; }

        public string GetKey(string key)
        {
            return this.Pairs[key].Value;
        }

        public void SetKey(string key, string value)
        {
            if(this.Pairs.ContainsKey(key))
            {
                KeyValuePair<string, string> pair = new KeyValuePair<string, string>(key, value);
                this.OrderedKeys.Insert(this.OrderedKeys.IndexOf(this.Pairs[key]), pair);
                this.Pairs[key] = pair;
            }
        }

        public Options()
        {
            LoadFile();
        }

        ~Options()
        {
            WriteFile();
        }

        private void LoadFile()
        {
            Regex regex = new Regex(@"(?<key>\S*?)\s*=\s*(?<val>\S*?)\s*\r\n");
            MatchCollection matches = regex.Matches(File.ReadAllText(FILENAME));

            this.OrderedKeys = new List<KeyValuePair<string, string>>();
            this.Pairs = new Dictionary<string, KeyValuePair<string, string>>();

            foreach (Match match in matches)
            {
                KeyValuePair<string, string> pair = 
                    new KeyValuePair<string,string>(match.Groups["key"].Value, match.Groups["val"].Value);

                this.OrderedKeys.Add(pair);
                this.Pairs.Add(pair.Key, pair);
            }
        }

        private void WriteFile()
        {
            if (File.Exists(FILENAME))
                File.Delete(FILENAME);

            using (System.IO.StreamWriter file = new System.IO.StreamWriter(FILENAME))
            {
                foreach (KeyValuePair<string, string> pair in this.OrderedKeys)
                {
                    file.WriteLine(pair.Key + " = " + pair.Value);
                }
            }
        }


    }

请注意,选项对象将从文件中读取一次,并在销毁时写出,同时它将保存文件中值的本地字典。然后您可以 GetKey() 和 SetKey() 来获取和设置您的选项。

我修改了我的原始帖子以使用列表和字典,这是因为字典本身不保持添加对的原始顺序,因此列表确保选项始终以正确的顺序写入文件。

您还会注意到我添加了一个正则表达式来解析您的文件,使事情变得更容易和更快,并允许在选项文件中添加额外的空格。

完成此操作后,很容易添加诸如

        public List<float> GetListFloatKey(string keybase)
        {
            List<float> ret = new List<float>();
            foreach (string key in this.Pairs.Keys)
            {
                if (Regex.IsMatch(key, keybase + "[0-9]+"))
                    ret.Add(float.Parse(this.Pairs[key].Value));
            }

            return ret;
        }

        public void SetListFloatKey(string keybase, List<float> values)
        {
            List<string> oldkeys = new List<string>();
            int startindex = -1;
            foreach (string key in this.Pairs.Keys)
            {
                if (Regex.IsMatch(key, keybase + "[0-9]+"))
                {
                    if (startindex == -1)
                        startindex = this.OrderedKeys.IndexOf(this.Pairs[key]);

                    oldkeys.Add(key);
                }
            }

            foreach (string key in oldkeys)
            {
                this.OrderedKeys.Remove(this.Pairs[key]);
                this.Pairs.Remove(key);
            }

            for (int i = 0; i < values.Count; i++)
            {
                KeyValuePair<string, string> pair = new KeyValuePair<string, string>(keybase + i.ToString(), values[i].ToString());
                if (startindex != -1)
                    this.OrderedKeys.Insert(startindex + i, pair);
                else
                    this.OrderedKeys.Add(pair);

                this.Pairs.Add(pair.Key, pair);
            }
        }

此时更容易做到这一点,因为您已经抽象出实际的文件结构,现在只处理字典

于 2012-07-05T06:14:53.983 回答