C # - чтение / копирование / замена строк в тексте - PullRequest
3 голосов
/ 29 июня 2011

У меня есть текстовый файл, который я открываю, и он имеет формат, аналогичный следующему:

  10 SOME TEXT
  20 T A40
  B B5, C45, D48
  30 B E25
  40 B F17, G18
  60 T H20, I23,
  B J6, K7, L8, M9, N10, O11, P12,
  Q31, R32, S33, T34, U35, V36,
  W37, X38, Y39
  100 T Z65
  360 B A1, B4, C5, D6, E7, F10
  2000 T SOME TEXT
  423 TEXT

С этим текстом мне нужно иметь возможность прочитать его и соответственно заменить значения. Если ReadLine начинается с числа (т. Е. 10, 20, 30, 40, 60, 100, 360, 2000, 423), мне нужно проверить, есть ли после него T, B или текст. Единственный случай, когда мне нужно изменить / переформатировать строки, когда они входят и выводят их по-разному.

Пример: 10 - это хорошо, за исключением того, что я хотел бы добавить нули перед каждым числом, чтобы они имели длину 4 цифры (т. Е. 10 витков до 0010, 360 витков до 0360, 2000 остается прежним). Когда читается строка «B B5, C45, D48» (это третья строка в тексте), мне нужно изменить ее на «20A B5, C45, D48». Мне нужно взять число над буквой «B», соединить его с буквой «B» и заменить букву «B» буквой «A». Если вместо «B» есть «T», мне просто нужно удалить «T». Кроме того, если строка не начинается с цифры или «B» (то есть, Q31 или W37), мне нужно сопоставить эту строку с предыдущей строкой.


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

  0010 SOME TEXT
  0020 A40
  0020A B5, C45, D48
  0030A E25
  0040A F17, G18
  0060 H20, I23,
  0060A J6, K7, L8, M9, N10, O11, P12, Q31, R32, S33, T34, U35, V36, W37, X38, Y39
  0100 Z65
  0360A A1, B4, C5, D6, E7, F10
  2000 SOME TEXT
  0423 TEXT

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

Вот так выглядит мой текущий вывод:

    0010A 
    0010
    0020A 
    0020

    0030A 
    0030
    0060A 
    0060



    0100A 
    0100
    0360A 
    0360
    2000
    2000
    0423A 
    0423

Я, очевидно, что-то делаю не так, используя Regex.

Вот мой текущий код:

    private void openRefsButton_Click(object sender, EventArgs e)
    {
        // Initialize the OpenFileDialog to specify the .txt extension as well as
        // its intial directory for the file.
        openRefs.DefaultExt = "*.txt";
        openRefs.Filter = ".txt Files|*.txt";
        openRefs.InitialDirectory = "C:\\";
        openRefs.RestoreDirectory = true;

        try
        {
            // Open the contents of the file into the originalTextRichTextBox.
            if (openRefs.ShowDialog() == DialogResult.OK && openRefs.FileName.Length > 0)
                refsTextRichTextBox.LoadFile(openRefs.FileName, RichTextBoxStreamType.PlainText);

            // Throws a FileNotFoundException otherwise.
            else
                throw new FileNotFoundException();

            StreamReader refsInput = File.OpenText(openRefs.FileName);

            string regExpression = @"^[\d]+";
            string findNewBottomRegex = @"^B\s";

            StringBuilder buildNumberText = new StringBuilder();
            StringBuilder formatMatchText = new StringBuilder();

            foreach (string allLines in File.ReadAllLines(openRefs.FileName))
            {
                Match newBottomMatch = Regex.Match(allLines, findNewBottomRegex);
                Match numberStartMatch = Regex.Match(allLines, regExpression);
                int counter = 0;

                if (counter < numberStartMatch.Length)
                {
                    if (numberStartMatch.Value.Length == 2)
                    {
                        if (refsTextRichTextBox.Text.Contains(newBottomMatch.ToString()))
                        {
                            finalTextRichTextBox.AppendText("00" + numberStartMatch + "A\n");
                        }

                        finalTextRichTextBox.AppendText("00" + numberStartMatch + "\n");
                    }

                    else if (numberStartMatch.Value.Length == 3)
                    {
                        if (refsTextRichTextBox.Text.Contains(newBottomMatch.ToString()))
                        {
                            finalTextRichTextBox.AppendText("0" + numberStartMatch + "A\n");
                        }

                        finalTextRichTextBox.AppendText("0" + numberStartMatch + "\n");
                    }

                    else
                    {
                        if (refsTextRichTextBox.Text.Contains(newBottomMatch.ToString()))
                        {
                            finalTextRichTextBox.AppendText(numberStartMatch + "A\n");
                        }

                        finalTextRichTextBox.AppendText(numberStartMatch + "\n");
                    }
                    counter++;
                }
            }
        }

        // Catches an exception if the file was not opened.
        catch (Exception)
        {
            MessageBox.Show("There was not a specified file path.", "Path Not Found Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }
}

}

ВОПРОС (S):

  • Как лучше выполнить эту задачу?
  • Есть ли какие-либо рекомендации по изменению моего кода, чтобы сделать его более эффективным и чистым?
  • Как правильно разделить каждую строку на число, T / B, A40, если каждая строка не совпадает?
  • После того, как строки правильно разделены, как мне заменить копию строки раньше, если текущая строка начинается с буквы "B"?
    • Если строка начинается с «Q31» или аналогичного, как мне добавить эту текущую строку в конец предыдущей?
  • Как только это произойдет, есть ли способ объединить все для создания указанного формата выше?

РАБОЧИЙ ПОТОК @ jaywayco

  • Открыть текстовый файл
  • Читать файл построчно
    • Сохранить каждую строку в списке строк
  • Разделить каждую строку на ''
  • Найдите каждую строку, которая начинается с цифры
    • Замените эту цифру, чтобы она имела длину 4 цифры
    • Проверьте следующий текст после цифры, чтобы увидеть, является ли это "B", "T" или "НЕКОТОРЫЙ ТЕКСТ"
      • если "B" скопировать строку выше
        • Добавить «А» в конце цифры
      • если "Т" убрать "Т"
      • если "НЕКОТОРЫЙ ТЕКСТ" ничего не делать
  • Найдите каждую строку, начинающуюся с буквы "B"
    • Скопируйте цифры в строке выше и вставьте в начало буквы "B".
      • Выполните шаг 4.b.i
  • Найдите каждую строку, начинающуюся (или похожую) с "Q31"
    • Свести эту строку в конец предыдущей строки
  • ...

Ответы [ 4 ]

2 голосов
/ 30 июня 2011

Вот действительно неубедительное процедурное решение:

using System.IO;
using System.Collections.Generic;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<string>();

            using (var reader = File.OpenText(@"c:\input.txt"))
            {
                while (true)
                {
                    var line = reader.ReadLine();
                    if (string.IsNullOrEmpty(line)) break;
                    list.Add(line);
                }
            }

            list = HandleRemoveTRequirement(list);
            list = HandleFourDigitRequirement(list);
            list = HandleConcatRequirement(list);
            list = HandleStartsWithBRequirement(list);
            list = HandleSecondElementIsBRequirement(list);

            using (var output = new StreamWriter(@"c:\output.txt"))
            {
                foreach (var line in list)
                {
                    output.WriteLine(line);
                }
            }
        }

        static List<string> HandleSecondElementIsBRequirement(List<string> list)
        {
            var result = new List<string>();

            foreach (var line in list)
            {
                var parts = line.Split(' ');

                if (parts[1].Equals("B"))
                {
                    parts[0] += "A";
                    parts[1] = string.Empty;
                    result.Add(string.Join(" ", parts).Replace("  ", " "));
                }
                else
                {
                    result.Add(line);
                }
            }

            return result;
        }

        static List<string> HandleStartsWithBRequirement(List<string> list)
        {
            var result = new List<string>();
            var i = 0;

            foreach (var line in list)
            {
                var parts = line.Split(' ');

                if (parts[0].Equals("B"))
                {
                    parts[0] = string.Empty;
                    result.Add(list[i - 1].Split(' ')[0] + "A" + string.Join(" ", parts));
                }
                else
                {
                    result.Add(line);
                }

                i++;
            }

            return result;
        }

        static List<string> HandleConcatRequirement(List<string> list)
        {
            var result = new List<string>();

            foreach (var line in list)
            {
                var parts = line.Split(' ');
                int test;
                if (int.TryParse(parts[0], out test) || parts[0].Equals("B"))
                {
                    result.Add(line);
                }
                else
                {
                    result[result.Count -1] += line;
                }
            }

            return result;
        }

        static List<string> HandleRemoveTRequirement(List<string> list)
        {
            var result = new List<string>();

            foreach (var line in list)
            {
                var parts = line.Split(' ');
                if (parts[1].Equals("T"))
                {
                    parts[1] = string.Empty;
                }
                result.Add(string.Join(" ", parts).Replace("  ", " "));
            }

            return result;
        }

        static List<string> HandleFourDigitRequirement(List<string> list)
        {
            var result = new List<string>();

            foreach (var line in list)
            {
                var parts = line.Split(' ');
                int test;
                if (int.TryParse(parts[0], out test))
                {
                    parts[0] = parts[0].PadLeft(4, '0');
                    result.Add(string.Join(" ", parts));
                }
                else
                {
                    result.Add(line);
                }
            }

            return result;
        }
    }
}
1 голос
/ 29 июня 2011

Один из способов приблизиться к этому - это аналог Jaywayco.

Я бы начал с размещения каждой строки, разделенной пробелами, в свой собственный массив. Поместите этот массив в массив массивов. Оттуда вы можете рассмотреть свой рабочий процесс. Ваш массив строк, разделенный пробелами, вы можете определить, как его печатать, исходя из первого значения, будь то число или буква B и т. Д. первое значение, которое будет числом и т. д. Вам придется немного подумать над логикой, но я думаю, вы понимаете, откуда я. Я не уверен, является ли это лучшим подходом или нет, но я думаю, что именно так я бы и решил. Удачи!

Редактировать: вот какой-то пародийный код ...

var mainArray = new Array[textFile.Count];  
//obviously get the count of number of lines set that to the size of your array object.

for(int i=0; i < mainArray.Length; i++)
{
     var line = methodToGetLineFromTextFile[i];
     string[] lineArray = line.Split(' ');
     mainArray[i] = lineArray;
}

//Once you have everything loaded into your arrays, apply your workflow logic.

Надеюсь, это поможет!

1 голос
/ 29 июня 2011

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

1 голос
/ 29 июня 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...