На мой взгляд, это отличная возможность использовать класс StringReader
:
- Читайте ваш текст построчно.
- Храните ваши строки в каком-то буфере (например,
Queue<string>
), удаляя ненужные строки после прочтения заданного количества строк.
- Как только ваша «игла» найдена, прочитайте еще одну строку (если возможно), а затем просто верните то, что находится в вашем буфере.
На мой взгляд, это имеет некоторые преимущества перед другими предлагаемыми подходами:
- Поскольку он не использует
String.Split
, он не выполняет больше работы, чем вам нужно - т.е. читает всю строку, ищет символы для разделения и создает массив подстроки.
- На самом деле, вовсе не обязательно читать всю строку вообще , поскольку, как только он находит искомый текст, он заходит настолько далеко, насколько необходимо, чтобы получить желаемое количество строк заполнения.
- Он может даже быть реорганизован (очень легко), чтобы иметь возможность обрабатывать любой текстовый ввод с помощью
TextReader
- например, StreamReader
- так что он мог бы работать даже с огромными файлами, без необходимости загружать все содержимое данного файла в память.
Представьте себе такой сценарий: вы хотите найти отрывок текста из текстового файла, который содержит весь текст романа. (Не то, что это ваш сценарий - я просто говорю гипотетически.) Использование String.Split
потребует, чтобы весь текст романа был разделен в соответствии с указанным вами разделителем, тогда как StringReader
(ну, в этом случае StreamReader
) потребуется только чтение до тех пор, пока не будет найден нужный текст, после чего будет возвращен отрывок.
Опять же, я понимаю, что это не обязательно ваш сценарий - просто предполагается, что этот подход обеспечивает масштабируемость как одну из его сильных сторон.
Вот быстрая реализация:
// rearranged code to avoid horizontal scrolling
public static string FindSurroundingLines
(string haystack, string needle, int paddingLines) {
if (string.IsNullOrEmpty(haystack))
throw new ArgumentException("haystack");
else if (string.IsNullOrEmpty(needle))
throw new ArgumentException("needle");
else if (paddingLines < 0)
throw new ArgumentOutOfRangeException("paddingLines");
// buffer needs to accomodate paddingLines on each side
// plus line containing the needle itself, so:
// (paddingLines * 2) + 1
int bufferSize = (paddingLines * 2) + 1;
var buffer = new Queue<string>(/*capacity*/ bufferSize);
using (var reader = new StringReader(haystack)) {
bool needleFound = false;
while (!needleFound && reader.Peek() != -1) {
string line = reader.ReadLine();
if (buffer.Count == bufferSize)
buffer.Dequeue();
buffer.Enqueue(line);
needleFound = line.Contains(needle);
}
// at this point either the needle has been found,
// or we've reached the end of the text (haystack);
// all that's left to do is make sure the string returned
// includes the specified number of padding lines
// on either side
int endingLinesRead = 0;
while (
(reader.Peek() != -1 && endingLinesRead++ < paddingLines) ||
(buffer.Count < bufferSize)
) {
if (buffer.Count == bufferSize)
buffer.Dequeue();
buffer.Enqueue(reader.ReadLine());
}
var resultBuilder = new StringBuilder();
while (buffer.Count > 0)
resultBuilder.AppendLine(buffer.Dequeue());
return resultBuilder.ToString();
}
}
Некоторые примеры ввода / вывода (с text
, содержащим ваш пример ввода):
Код:
Console.WriteLine(FindSurroundingLines(text, "MOUSE", 1);
Выход:
This is the 2nd line of BIRD text in the paragraph
This is the 3rd line of MOUSE text in the paragraph
This is the 4th line of DOG text in the paragraph
Код:
Console.WriteLine(FindSurroundingLines(text, "BIRD", 1);
Выход:
This is the 1st line of CAT text in the paragraph
This is the 2nd line of BIRD text in the paragraph
This is the 3rd line of MOUSE text in the paragraph
Код:
Console.WriteLine(FindSurroundingLines(text, "DOG", 0);
Выход:
This is the 4th line of DOG text in the paragraph
Код:
Console.WriteLine(FindSurroundingLines(text, "This", 2);
Выход:
This is the 1st line of CAT text in the paragraph
This is the 2nd line of BIRD text in the paragraph
This is the 3rd line of MOUSE text in the paragraph
This is the 4th line of DOG text in the paragraph
This is the 5th line of RABBIT text in the paragraph