解析文本文件的多个部分

本文关键字:个部 文件 文本 | 更新日期: 2023-09-27 17:53:42

首先让我感谢大家成为这个网站的一部分,我已经从这里获得了很多有用的信息。包括对数组中文本文件的一些基本解析,但我现在想更进一步。

我有一个像这样的文本文件

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

我以"start Section 1 - foods"作为数组元素之一结束。我可以用代码删除它,但有没有一种简单的方法来避免这种情况,所以只有列表项得到填充?

干杯,再次感谢所有的帮助。在这么多年之后又回到编程领域真是太棒了。亚伦

解析文本文件的多个部分

阅读行不是问题,参见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"];

查找开始和结束的指针。这是你开始把东西放入数组、列表等的地方。

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

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

对于其他的答案,如果您不想自己解析文本文件,那么您总是可以使用一个快速而肮脏的正则表达式,如果您对它们感到满意的话:

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"

对评论的回应:

但是"list"听起来很简单和基本(就像我在购物一样),数组有听起来好多了;)但是我会的再多看看他们,我从我的研究中得到了这个印象数组是更有效的代码?

这不是关于列表和数组是"基本的"还是"有一个更好的环",这是关于代码的目的。在您的示例中,您正在逐行迭代文件,并事先将项添加到未知大小的集合中—这是列表设计用于解决的一个问题。当然,您可以浏览文件并确定确切的大小,但是这样做是否值得您从使用数组中获得额外的"效率",并且两次迭代文件是否会比首先使用列表花费更长时间?你不知道,除非你分析你的代码,并得出结论,特定的部分是一个瓶颈…我想说的是,这几乎是不可能的。

嗯,像这样?

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