0

オプション ファイルには、GetKey と SetKey の 2 つの関数があります。

キーを設定すると、settings_file.txt で次のようになります。

text = helloここで、textはキー then = であり、helloは現在のキーの値です。

次に、別の 2 つの関数を追加する必要があります。最初の関数は、文字列を取得してリストを返すリスト型です。

そして、キーとリストを取得する別の関数。

したがって、これは GetKey と SetKey で既に機能している最初の 2 つの関数です。

/*----------------------------------------------------------------
 * 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;

    }

この2つの機能の後、私は次のことを行いました:

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は、テキストファイルsettings_file.txtの結果です。

座標01 = 123

座標02 = 144

座標03 = 145

リスト内のすべてのセル/インデックスについて、キーを作成します。私が必要としているのは、取得したリストに 1 つのキーがあり、テキスト ファイルの形式は次のようになることです。

座標 = 123,144,145 ...... など、1 つのキーで取得し、リストからすべての値を取得します。

次に、GetListFloatKey で、座標などのキーに従って値を再フォーマットし、インデックス 0 123、1 144、2 145 などの値を持つリストを返す必要があります。

GetKey と SetKey の両方で使用する方法で、関数がそれらを実行する方法が優れているかどうかの問題はありますか? また、値をフォーマットして再フォーマットするにはどうすればよいですか?

4

2 に答える 2

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


    }

オプション オブジェクトはファイルから 1 回読み取り、破棄されると書き出すことに注意してください。その間、ファイル内の値のローカル ディクショナリが保持されます。次に、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 に答える
0

現時点では、リスト内のすべての項目に対して SetListFloatKey 内で SetKey を呼び出しています。代わりに、次の行に沿って文字列を作成し、それを 1 回呼び出す必要があります (基本的なテストは完了しています)。

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 = ",";
  }

...そしてもう 1 つは、SetKey の呼び出しでそれを除外することです...

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

..これらの両方のケースで、作業を容易にするためにコンマを先頭に移動したことに注意してください。または、数値を配列に格納し、Array.Join を使用することもできます。

于 2012-07-05T05:29:01.533 に答える