解析文本文件C#的多个部分

时间:2011-04-26 21:45:11

标签: c# parsing text

首先让我首先感谢大家参与此网站,我已经从中获得了很多有用的信息。包括一些基本的文本文件解析到数组,但我现在想更进一步。

我有一个看起来像这样的文本文件

Start Section 1 - foods

apple  
bannana  
pear   
pineapple  
orange  

end section 1

Start section 2 - animals

dog  
cat  
horse  
cow  

end section 2 

我想要做的是使用文件的单个读取将第1部分中的数据复制到名为“foods”的数组中,将第2部分复制到名为“animals”的数组中

现在我可以通过为每个部分使用一个新循环,每次关闭并重新打开文件,循环直到找到我想要的部分并创建数组来使其工作。

但我认为必须有一种方法可以一次性将每个部分读入一个单独的数组。

所以我目前的代码是

List<string> typel = new List<string>();  

using (StreamReader reader = new StreamReader("types.txt")) // opens file using streamreader
        {

            string line; // reads line by line in to varible "line"
            while ((line = reader.ReadLine()) != null) // loops untill it reaches an empty line
            {
                typel.Add(line); // adds the line to the list varible "typel"
                               }

        }

        Console.WriteLine(typel[1]);  // test to see if list is beeing incremented
        string[] type = typel.ToArray(); //converts the list to a true array 
        Console.WriteLine(type.Length); // returns the number of elements of the array created. 

这是一个简单的文本文件,没有任何部分只是值列表,使用list似乎是处理未知长度数组的好方法。

我也想知道如何处理第一个值。

例如,如果我做

while ((line = reader.ReadLine()) != Start Section 1 - foods)  
{  
}  
while ((line = reader.ReadLine()) != end Section 1)   
{  
foods.Add(line);  
}  
...  
....

我最终将“开始第1节 - 食物”作为阵列元素之一。我可以用代码删除它,但是有一种简单的方法可以避免这种情况,所以只填充列表项吗?

干杯再次感谢所有的帮助。很多年后重新开始编程很棒。

亚伦

4 个答案:

答案 0 :(得分:4)

阅读这些内容不是问题,请参阅System.IO.ReadAllLines(fileName)及其兄弟姐妹。

你需要的是一个(非常简单的)翻译:

// totally untested
Dictionary<string, List<string>> sections = new Dictionary<string, List<string>>();
List<string> section = null;

foreach(string line in GetLines())
{
   if (IsSectionStart(line))
   {
      string name = GetSectionName(line);
      section = new List<string>();
      sections.Add(name, section);
   }
   else if (IsSectionEnd(line))
   {          
      section = null;  // invite exception when we're lost
   }
   else
   {
      section.Add(line);
   }
}


...
List<string> foods = sections ["foods"];

答案 1 :(得分:3)

寻找开始和结束的指针。这是您开始将数据放入数组,列表等的地方。

这是一个非常灵活的尝试:

class Program
{
    private static Dictionary<string, List<string>> _arrayLists = new Dictionary<string, List<string>>();

    static void Main(string[] args)
    {
        string filePath = "c:\\logs\\arrays.txt";
        StreamReader reader = new StreamReader(filePath);
        string line;
        string category = "";

        while (null != (line = reader.ReadLine()))
        {
            if (line.ToLower().Contains("start"))
            {
                string[] splitHeader = line.Split("-".ToCharArray());
                category = splitHeader[1].Trim();
            }
            else
            {
                if (!_arrayLists.ContainsKey(category))
                {
                    List<string> stringList = new List<string>();
                    _arrayLists.Add(category, stringList);
                }

                if((!line.ToLower().Contains("end")&&(line.Trim().Length > 0)))
                {
                    _arrayLists[category].Add(line.Trim());
                }
            }
        }

        //testing
        foreach(var keyValue in _arrayLists)
        {
            Console.WriteLine("Category: {0}",keyValue.Key);
            foreach(var value in keyValue.Value)
            {
                Console.WriteLine("{0}".PadLeft(5, ' '), value);
            }
        }


        Console.Read();
    }
}

答案 2 :(得分:2)

要添加其他答案,如果您不想自己解析文本文件,如果您对它们感到满意,可以使用快速且脏的正则表达式:

var regex = new Regex(@"Start Section \d+ - (?<section>\w+)\r\n(?<list>[\w\s]+)End Section", RegexOptions.IgnoreCase);

var data = new Dictionary<string, List<string>>();

foreach (Match match in regex.Matches(File.ReadAllText("types.txt")))
{
    string section = match.Groups["section"].Value;
    string[] items = match.Groups["list"].Value.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

    data.Add(section, new List<string>(items));
}

// data["animals"] now contains a list of "dog", "cat", "horse", and "cow"

回应评论:

  

但“列表”听起来如此简单和基本   (就像我要去购物),阵列有   更好的戒指;)但我会   再看看他们可能会多一些,我   从我的研究中得到了印象   那些数组是更有效的代码吗?

这不是关于列表与数组是“基本”还是“有更好的响铃”,而是关于代码的目的。在您的情况下,您将逐行迭代文件并事先将项目添加到未知大小的集合中 - 这是列表旨在解决的一个问题。当然你可以查看文件并确定确切的大小,但这样做是否值得你使用数组获得的额外“效率”,并且迭代文件两次比首先使用列表需要更长的时间?你不知道,除非你描述你的代码并得出结论,特定部分是一个瓶颈......我会说,几乎不会是这种情况。

答案 3 :(得分:0)

嗯,好像这样?

//converting it to array called allLines, elements/index per line
string[] allLines = File.ReadAllLines("types.txt").ToArray();

//getting the index of allLines that contains "Start Section 1" and "end section 1" 
int[] getIndexes = new int[] { Array.FindIndex(allLines, start => start.Contains("Start Section 1")), Array.FindIndex(allLines, start => start.Contains("end section 1")) };

//create list to get indexes of the list(apple,banana, pear, etc...)
List<int> indexOfList = new List<int>();

//get index of the list(apple,banana, pear,etc...)
for (int i = getIndexes[0]; i < getIndexes[1]; i++)
{
    indexOfList.Add(i);
}

//remove the index of the element or line "Start Section 1"
indexOfList.RemoveAt(0);
//final list
string[] foodList = new string[]{ allLines[indexOfList[0]], allLines[indexOfList[1]], and so on...};

然后你可以打电话给他们或编辑然后保存。

//call them
Console.Writeline(foodList[0] + "\n" + foodList[1] + ...)

//edit the list
allLines[indexOfList[0]] = "chicken"; //from apple to chicken
allLines[indexOfList[1]] = "egg"; //from banana to egg
//save lines
File.WriteAllLines("types.txt", allLines);