C #: Цикл по строкам многострочной строки

Каков хороший способ перебрать каждую строку многострочной строки без использования гораздо большего объема памяти (например, без разделения ее на массив)?


person flamey    schedule 30.09.2009    source источник


Ответы (8)


Я предлагаю использовать комбинацию StringReader и моего LineReader класса, который является частью MiscUtil, но также доступен в ответе на StackOverflow - вы можете легко скопировать только этот класс в свой собственный инженерный проект. Вы бы использовали это так:

string text = @"First line
second line
third line";

foreach (string line in new LineReader(() => new StringReader(text)))
{
    Console.WriteLine(line);
}

Цикл по всем строкам в теле строковых данных (будь то файл или что-то еще) настолько распространен, что не должен требовать, чтобы вызывающий код проверял на ноль и т. Д. :) Сказав это, если вы сделаете < / em> хочу выполнить ручной цикл, это форма, которую я обычно предпочитаю Фредрику:

using (StringReader reader = new StringReader(input))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        // Do something with the line
    }
}

Таким образом, вам нужно только один раз проверить нулевое значение, и вам не нужно думать о цикле do / while (который по какой-то причине всегда требует больше усилий для чтения, чем прямой цикл while).

person Jon Skeet    schedule 30.09.2009
comment
Похоже, у MiscUtil нет версии для .NET Core. - person void.pointer; 13.03.2021
comment
@ void.pointer: Нет, боюсь. Это не тот проект, над которым я когда-либо работал за последние 10 лет. - person Jon Skeet; 14.03.2021
comment
StringReader, объект мало что знать. Спасибо. Это было то, что мне нужно. - person RogerEdward; 11.05.2021

Вы можете использовать StringReader для чтения строки в время:

using (StringReader reader = new StringReader(input))
{
    string line = string.Empty;
    do
    {
        line = reader.ReadLine();
        if (line != null)
        {
            // do something with the line
        }

    } while (line != null);
}
person Fredrik Mörk    schedule 30.09.2009
comment
Здорово; +1; это помогло; но я просто хочу добавить, что на самом деле нет необходимости использовать блок using, потому что в этом случае нет никаких ресурсов, которые можно было бы закрыть. См. Примечания в статье StringReader на docs.microsoft.com - person R.D. Alkire; 30.01.2020

Я знаю, что на это есть ответ, но я хотел бы добавить свой ответ:

using (var reader = new StringReader(multiLineString))
{
    for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
    {
        // Do something with the line
    }
}
person Niels    schedule 06.02.2017
comment
Мне нравится, насколько это кратко. ты. - person CANDIMAN; 18.04.2021

из MSDN для StringReader

    string textReaderText = "TextReader is the abstract base " +
        "class of StreamReader and StringReader, which read " +
        "characters from streams and strings, respectively.\n\n" +

        "Create an instance of TextReader to open a text file " +
        "for reading a specified range of characters, or to " +
        "create a reader based on an existing stream.\n\n" +

        "You can also use an instance of TextReader to read " +
        "text from a custom backing store using the same " +
        "APIs you would use for a string or a stream.\n\n";

    Console.WriteLine("Original text:\n\n{0}", textReaderText);

    // From textReaderText, create a continuous paragraph 
    // with two spaces between each sentence.
    string aLine, aParagraph = null;
    StringReader strReader = new StringReader(textReaderText);
    while(true)
    {
        aLine = strReader.ReadLine();
        if(aLine != null)
        {
            aParagraph = aParagraph + aLine + " ";
        }
        else
        {
            aParagraph = aParagraph + "\n";
            break;
        }
    }
    Console.WriteLine("Modified text:\n\n{0}", aParagraph);
person tster    schedule 30.09.2009

Чтобы обновить этот древний вопрос для .NET 4, теперь есть более простой способ:

var lines = File.ReadAllLines(filename);

foreach (string line in lines)
{
    Console.WriteLine(line);
}
person NickG    schedule 28.08.2018

Вот небольшой фрагмент кода, который найдет первую непустую строку в строке:

string line1;
while (
    ((line1 = sr.ReadLine()) != null) &&
    ((line1 = line1.Trim()).Length == 0)
)
{ /* Do nothing - just trying to find first non-empty line*/ }

if(line1 == null){ /* Error - no non-empty lines in string */ }
person palswim    schedule 11.10.2010

Попробуйте использовать метод String.Split:

string text = @"First line
second line
third line";

foreach (string line in text.Split('\n'))
{
    // do something
}
person emmediemme82    schedule 03.07.2020

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

Поразмыслив немного, я пришел к выводу, что самое простое решение - повторить ReadLine до и внутри цикла.

using (var stringReader = new StringReader(input))
{
    var line = await stringReader.ReadLineAsync();

    while (line != null)
    {
        // do something
        line = await stringReader.ReadLineAsync();
    }
}

Я понимаю, что это может рассматриваться как нарушение принципа DRY, но я думаю, что это стоит рассмотреть, учитывая простоту.

person craftworkgames    schedule 28.11.2020