Разбор нескольких разделов текстового файла C # - PullRequest
5 голосов
/ 27 апреля 2011

Прежде всего позвольте мне поблагодарить вас всех за то, что вы являетесь частью этого сайта, я уже получил от него столько полезной информации.включая некоторые базовые разборы текстовых файлов в массивах, но теперь я хочу пойти дальше.

У меня есть текстовый файл, который выглядит примерно так

Start Section 1 - foods

apple  
bannana  
pear   
pineapple  
orange  

end section 1

Start section 2 - animals

dog  
cat  
horse  
cow  

end section 2 

, что я хочу сделать, это с помощью одного чтения файла скопировать данные из раздела 1 в массив с именем«Еда» и раздел 2 в массиве «животные»

Теперь я могу заставить его работать, используя новый цикл для каждого раздела, закрывая и открывая файл каждый раз, повторяя цикл, пока не найду разделЯ хочу и создание массива.

Но я подумал, что должен быть способ прочитать каждый раздел в отдельный массив за один раз, экономя время.

, поэтому мой текущий код -

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. 

, который предназначен для простого текстового файла без разделов, а только для списка значений, использование списка казалось хорошим способом справиться с неизвестными длинами массивов.

Мне также было интересно, как поступить с первым значением.

например, если я сделаю

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

, я получу «начало раздела 1 - продукты» в качестве одного из элементов массива.Я могу удалить его с помощью кода, но есть ли простой способ избежать этого, чтобы заполнить только элементы списка?

Приветствия и еще раз спасибо за помощь.Здорово вернуться к программированию через много-много лет.

Аарон

Ответы [ 4 ]

4 голосов
/ 27 апреля 2011

Чтение строк не является проблемой, см. 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"];
3 голосов
/ 27 апреля 2011

Ищите указатели для начала и конца.Здесь вы начинаете помещать вещи в массивы, списки и т. Д.

Вот пример того, как сделать его очень гибким:

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 голосов
/ 27 апреля 2011

Чтобы добавить к другим ответам, если вы не хотите анализировать текстовый файл самостоятельно, вы всегда можете использовать быстрое и грязное регулярное выражение, если вам удобно:

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"

В ответ на комментарий:

но "список" звучит так просто и просто (как я иду по магазинам), массив имеет гораздо приятнее звонить;) но я буду посмотрите на них, может быть, немного больше, я получил впечатление от моего исследования что массивы являются более эффективным кодом?

Дело не в том, является ли список или массив "базовым" или "имеет более приятное звучание", а в том, для чего предназначен код. В вашем случае вы перебираете файл построчно и заранее добавляете элементы в коллекцию неизвестного размера - это одна из проблем, которую должен был решить список. Конечно, вы можете просмотреть файл и определить точный размер, но стоит ли это того, чтобы получить дополнительную «эффективность», которую вы получаете от использования массива, и повторение файла дважды займет больше времени, чем использование списка? Вы не узнаете, если не профилируете свой код и не решите, что определенная часть является узким местом ... что, я скажу, почти никогда не будет иметь место.

0 голосов
/ 22 марта 2016

Ммм, как это?

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