1

数百の構成値を持つテキストファイルがあります。構成データの一般的な形式は「Label:Value」です。C#.netを使用して、これらの構成を読み、コードの他の部分で値を使用したいと思います。私の最初の考えは、文字列検索を使用してラベルを検索し、ラベルに続く値を解析して辞書に追加することですが、検索する必要のあるラベル/値の数を考えると、これはかなり面倒なようです。 。このタスクを実行するための可能なアーキテクチャについての考えを聞いて興味があります。いくつかのラベルと値を含むサンプルテキストファイルの小さなセクションを含めました(以下)。注意事項:値は常に数値であるとは限りません(AUXシリアル番号に表示されます)。理由はともかく、テキストファイルは、タブ(\ t)ではなくスペース(\ s)を使用してフォーマットされました。あなたがこれについて考えるのに費やすどんな時でも前もって感謝します。

サンプルテキスト:

 AUX Serial Number:  445P000023       AUX Hardware Rev:           1

 Barometric Pressure Slope:     -1.452153E-02
 Barometric Pressure Intercept: 9.524336E+02
4

6 に答える 6

5

これは素敵な小さな脳のくすぐりです。このコードはあなたを正しい方向に向けることができるかもしれないと思います。これはaを埋めるためDictionary<string, string>、値がintなどに変換されないことに注意してください。また、混乱(および不適切な命名規則)を許してください。それは私の思考の流れに基づいた簡単な記事でした。

Dictionary<string, string> allTheThings = new Dictionary<string, string>();

public void ReadIt()
{
    // Open the file into a streamreader
    using (System.IO.StreamReader sr = new System.IO.StreamReader("text_path_here.txt"))
    {
        while (!sr.EndOfStream) // Keep reading until we get to the end
        {
            string splitMe = sr.ReadLine();
            string[] bananaSplits = splitMe.Split(new char[] { ':' }); //Split at the colons

            if (bananaSplits.Length < 2) // If we get less than 2 results, discard them
                continue; 
            else if (bananaSplits.Length == 2) // Easy part. If there are 2 results, add them to the dictionary
                allTheThings.Add(bananaSplits[0].Trim(), bananaSplits[1].Trim());
            else if (bananaSplits.Length > 2)
                SplitItGood(splitMe, allTheThings); // Hard part. If there are more than 2 results, use the method below.
        }
    }
}

public void SplitItGood(string stringInput, Dictionary<string, string> dictInput)
{
    StringBuilder sb = new StringBuilder();
    List<string> fish = new List<string>(); // This list will hold the keys and values as we find them
    bool hasFirstValue = false;

    foreach (char c in stringInput) // Iterate through each character in the input
    {
        if (c != ':') // Keep building the string until we reach a colon
            sb.Append(c);
        else if (c == ':' && !hasFirstValue)
        {
            fish.Add(sb.ToString().Trim());
            sb.Clear();
            hasFirstValue = true;
        }
        else if (c == ':' && hasFirstValue)
        {

            // Below, the StringBuilder currently has something like this:
            // "    235235         Some Text Here"
            // We trim the leading whitespace, then split at the first sign of a double space
            string[] bananaSplit = sb.ToString()
                                     .Trim()
                                     .Split(new string[] { "  " },
                                            StringSplitOptions.RemoveEmptyEntries);

            // Add both results to the list
            fish.Add(bananaSplit[0].Trim());
            fish.Add(bananaSplit[1].Trim());
            sb.Clear();
        }                    
    }

    fish.Add(sb.ToString().Trim()); // Add the last result to the list

    for (int i = 0; i < fish.Count; i += 2)
    {
        // This for loop assumes that the amount of keys and values added together
        // is an even number. If it comes out odd, then one of the lines on the input
        // text file wasn't parsed correctly or wasn't generated correctly.
        dictInput.Add(fish[i], fish[i + 1]); 
    }
}
于 2012-11-20T19:14:59.383 に答える
0

したがって、制限されている形式を考えると、私が考えることができる唯一の一般的なアプローチは、最初に行の最初のコロンを見つけて、その前のすべてをラベルとして使用することです。最初の非空白文字に到達するまで、すべての空白文字をスキップします。ラベルの値として、空白以外のすべての文字を使用します。その値の終わりの後にコロンがある場合は、前の値の終わり以降のすべてを次の値としてコロンに取り、繰り返します。また、おそらくラベルの周りの空白を削除する必要があります。

正規表現でその意味を捉えることができるかもしれませんが、できればそれはおそらくきれいなものではないでしょう。開発チーム全体がそれらに非常に精通しているのでない限り、私はこの複雑な何かのためにそれを避けたいと思います。

于 2012-11-20T17:42:09.897 に答える
0

私はこのようなことを試みます:

  1. 文字列にはトリプルスペースが含まれていますが、ダブルスペースに置き換えてください。
  2. すべての「:」と「:」(:ダブルスペース付き)を「:」に置き換えます。
  3. すべての""(ダブルスペース)を'\ n'(改行)に置き換えます。
  4. 行に「:」が含まれていない場合は、行をスキップします。それ以外の場合は、string.Split(':')を使用します。このようにして、2つの文字列(キーと値)の配列を受け取ります。それらのいくつかは、最初または最後に空の文字を含む場合があります。
  5. string.Trim()を使用して、これらの空の文字を取り除きます。
  6. 受信したキーと値を辞書に追加します。

それがあなたのすべてのケースを解決するかどうかはわかりませんが、それは私がそれをどのようにしようとするかについての一般的な手がかりです。それが機能する場合は、パフォーマンスについて考えることができます(可能な限り文字列の代わりにStringBuilderを使用するなど)。

于 2012-11-20T18:04:35.477 に答える
0

これはおそらく私が今まで書いた中で最も汚い関数ですが、機能します。

            StreamReader reader = new StreamReader("c:/yourFile.txt");

            Dictionary<string, string> yourDic = new Dictionary<string, string>();            

            StreamReader reader = new StreamReader("c:/yourFile.txt");

            Dictionary<string, string> yourDic = new Dictionary<string, string>();

            while (reader.Peek() >= 0)
            {
                string line = reader.ReadLine();
                string[] data = line.Split(':');

                if (line != String.Empty)
                {
                    for (int i = 0; i < data.Length - 1; i++)
                    {
                        if (i != 0)
                        {
                            bool isPair;
                            if (i % 2 == 0)
                            {
                                isPair = true;
                            }
                            else
                            {
                                isPair = false;
                            }

                            if (isPair)
                            {
                                string keyOdd = data[i].Trim();
                                try { keyOdd = keyOdd.Substring(keyOdd.IndexOf(' ')).TrimStart(); }
                                catch { }
                                string valueOdd = data[i + 1].TrimStart();
                                try { valueOdd = valueOdd.Remove(valueOdd.IndexOf(' ')); } catch{}
                                yourDic.Add(keyOdd, valueOdd);
                            }
                            else
                            {
                                string keyPair = data[i].TrimStart();
                                keyPair = keyPair.Substring(keyPair.IndexOf(' ')).Trim();
                                string valuePair = data[i + 1].TrimStart();
                                try { valuePair = valuePair.Remove(valuePair.IndexOf(' ')); } catch { }
                                yourDic.Add(keyPair, valuePair);
                            }

                        }
                        else
                        {
                            string key = data[i].Trim();
                            string value = data[i + 1].TrimStart();
                            try { value = value.Remove(value.IndexOf(' ')); } catch{}
                            yourDic.Add(key, value);
                        }
                    }
                }
            }

それはどのように機能しますか?、行をうまく分割すると、配列のすべての位置で何を取得できるかを知ることができるので、私は偶数と奇数の値で遊んでいます。この関数をデバッグすると、私を理解できます:D。それはあなたが必要とする辞書を満たします。

于 2012-11-20T20:25:51.287 に答える
0

別の考えがあります。値にスペースが含まれていますか?そうでない場合は、次のようにすることができます。

  1. 他の文字(キーの最初の文字)を読み取るまで、空白は無視してください。
  2. ':'が発生するまで文字列を読み取ります。
  3. 取得したトリムキー。
  4. 他の文字(値の最初の文字)を読み取るまで、空白は無視してください。
  5. 空の文字が表示されるまで読んでください。
  6. 取得した値をトリミングします。
  7. 止まるより終わりなら。それ以外の場合は、手順1に戻ります。

幸運を。

于 2012-11-21T11:24:04.110 に答える
-1

たぶんこのようなものがうまくいくでしょう、「:」文字に注意してください

            StreamReader reader = new StreamReader("c:/yourFile.txt");

            Dictionary<string, string> yourDic = new Dictionary<string, string>();

            while (reader.Peek() >= 0)
            {
                 string line = reader.ReadLine();
                 yourDic.Add(line.Split(':')[0], line.Split(':')[1]);
            }

とにかく、ファイルがどの形式であるかを常に把握できるように、そのファイルを整理することをお勧めします。

于 2012-11-20T17:43:07.507 に答える