C#: Looping through lines of multiline string

C#LoopsMultilinestring

C# Problem Overview


What is a good way to loop through each line of a multiline string without using much more memory (for example without splitting it into an array)?

C# Solutions


Solution 1 - C#

I suggest using a combination of StringReader and my LineReader class, which is part of MiscUtil but also available in this StackOverflow answer - you can easily copy just that class into your own utility project. You'd use it like this:

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

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

Looping over all the lines in a body of string data (whether that's a file or whatever) is so common that it shouldn't require the calling code to be testing for null etc :) Having said that, if you do want to do a manual loop, this is the form that I typically prefer over Fredrik's:

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

This way you only have to test for nullity once, and you don't have to think about a do/while loop either (which for some reason always takes me more effort to read than a straight while loop).

Solution 2 - C#

You can use a StringReader to read a line at a time:

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

Solution 3 - C#

I know this has been answered, but I'd like to add my own answer:

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

Solution 4 - C#

from MSDN for 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);

Solution 5 - C#

Here's a quick code snippet that will find the first non-empty line in a string:

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 */ }

Solution 6 - C#

Try using String.Split Method:

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

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

Solution 7 - C#

Sometimes I think we can overcomplicate the solution just to avoid repeating one line of code. This is the reason I landed on this question in the first place.

After thinking about it for a bit I came to the conclusion that the simplest solution is to repeat the ReadLine before and inside the loop.

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

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

I realize this might be considered to not follow the DRY principle, but I think it's worth considering given the simplicity.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionflameyView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Fredrik MörkView Answer on Stackoverflow
Solution 3 - C#NielsView Answer on Stackoverflow
Solution 4 - C#tsterView Answer on Stackoverflow
Solution 5 - C#palswimView Answer on Stackoverflow
Solution 6 - C#emmediemme82View Answer on Stackoverflow
Solution 7 - C#craftworkgamesView Answer on Stackoverflow