1

我有一个包含数百个配置值的文本文件。配置数据的一般格式是“Label:Value”。使用 C# .net,我想阅读这些配置,并在代码的其他部分使用这些值。我的第一个想法是我会使用字符串搜索来查找标签,然后解析出标签后面的值并将它们添加到字典中,但考虑到我必须搜索的标签/值的数量,这似乎相当乏味. 我很想听听有关执行此任务的可能架构的一些想法。我已经包含了一个示例文本文件的一小部分,其中包含一些标签和值(如下)。一些注意事项: 值并不总是数字(如 AUX 序列号所示);不管什么原因,文本文件使用空格 (\s) 而不是制表符 (\t) 进行格式化。提前感谢您花时间思考这个问题。

示例文本:

 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>,因此没有将值转换为整数等。另外,请原谅混乱(以及糟糕的命名约定)。这是根据我的思路快速写的。

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

我有另一个想法。值是否包含空格?如果没有,你可以这样做:

  1. 忽略空格,直到您读取一些其他字符(键的第一个字符)。
  2. 读取字符串直到 ':' 出现。
  3. 你得到的修剪钥匙。
  4. 忽略空格,直到您读取其他字符(值的第一个字符)。
  5. 阅读直到你得到空字符。
  6. 修剪你得到的价值。
  7. 如果它是结束比停止。否则,返回步骤 1。

祝你好运。

于 2012-11-21T11:24:04.110 回答
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

因此,鉴于您受限于格式,我能想到的唯一通用方法是首先找到该行的第一个冒号并将其前面的所有内容作为标签。跳过所有 whilespace 字符,直到您到达第一个非空白字符。将所有非空白字符作为标签的值。如果该值结束后有一个冒号,则将前一个值结束后的所有内容作为下一个值并重复。您可能还需要修剪标签周围的空白。

您可能可以使用正则表达式来捕捉该含义,但如果可以的话,它可能不会是一个漂亮的含义;除非您整个开发团队都非常精通它们,否则我会避免使用这种复杂的东西。

于 2012-11-20T17:42:09.897 回答
0

我会尝试这样的事情:

  1. 当字符串包含三倍空格时,将其替换为双倍空格。
  2. 将所有“:”和“:”(:带双空格)替换为“:”。
  3. 将所有“”(双空格)替换为 '\n'(新行)。
  4. 如果行不包含 ':' 则跳过该行。否则,使用 string.Split(':')。这样,您将收到 2 个字符串(键和值)的数组。其中一些可能在开头或结尾包含空字符。
  5. 使用 string.Trim() 去除那些空字符。
  6. 将接收到的键和值添加到字典。

我不确定它是否能解决你所有的情况,但这是我将如何尝试做的一般线索。如果它有效,您可以考虑性能(尽可能使用 StringBuilder 而不是 string 等)。

于 2012-11-20T18:04:35.477 回答
-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 回答