ReadAllLines for a Stream object?

C#FileTextStream

C# Problem Overview


There exists a File.ReadAllLines but not a Stream.ReadAllLines.

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    // Would prefer string[] result = reader.ReadAllLines();
    string result = reader.ReadToEnd();
}

Does there exist a way to do this or do I have to manually loop through the file line by line?

C# Solutions


Solution 1 - C#

You can write a method which reads line by line, like this:

public IEnumerable<string> ReadLines(Func<Stream> streamProvider,
                                     Encoding encoding)
{
    using (var stream = streamProvider())
    using (var reader = new StreamReader(stream, encoding))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

Then call it as:

var lines = ReadLines(() => Assembly.GetExecutingAssembly()
                                    .GetManifestResourceStream(resourceName),
                      Encoding.UTF8)
                .ToList();

The Func<> part is to cope when reading more than once, and to avoid leaving streams open unnecessarily. You could easily wrap that code up in a method, of course.

If you don't need it all in memory at once, you don't even need the ToList...

Solution 2 - C#

The .EndOfStream property can be used in the loop instead of checking if the next line is not null.

List<string> lines = new List<string>();

using (StreamReader reader = new StreamReader("example.txt"))
{
    while(!reader.EndOfStream)
    {
        lines.Add(reader.ReadLine());
    }
}

Solution 3 - C#

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    // Would prefer string[] result = reader.ReadAllLines();
    string[] result = reader.ReadToEnd().Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
}

Solution 4 - C#

The use of Split here:

reader
   .ReadToEnd()
   .Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

is not equivalent to ReadLine. If you look at the source for ReadLine, StreamReader.cs, you will see that it handles line terminators: \r, \n, and \r\n correctly. ReadLine does not return an extra empty string when the line terminator is \r\n, which is typical in DOS/Windows. Split "sees" (parses) \r followed by \n as 2 separate delimiters and returns an empty string.

'StringSplitOptions.RemoveEmptyEntries' in the above code does remove these empty strings, but it will also remove any empty lines which appear in the input as well.

Thus for the input line1\r \r line3\r ReadLine returns 3 lines. The 2nd is empty. Split creates 4 strings. (There is an additional string after the last \r.) It then removes the 2nd and the 4th.

Note that Split is not well suited to parsing text lines which are "post-fix" delimited. That is the delimiter appears after the token. While Split is suitable for infix, where the delimiters appear between the tokens. It is the difference between a,b,c and line1\r,line2,line3\r. For these inputs, Split returns 3 strings or 4 strings respectively.

Solution 5 - C#

Using the following extension method:

public static class Extensions
{
    public static IEnumerable<string> ReadAllLines(this StreamReader reader)
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

It's possible to get to your desired code:

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    string[] result = reader.ReadAllLines().ToArray();
}

Solution 6 - C#

If you want to use StreamReader then yes, you will have to use ReadLine and loop throught the StreamReader, reading line by line.

Something like that:

string line;

using (StreamReader reader = new StreamReader(stream))
{
	while ((line = reader.ReadLine()) != null)
	{	
		Console.WriteLine(line); 
	}
}

or try

using (StreamReader reader = new StreamReader("file.txt"))
	{
	    
	   string[] content = reader.ReadToEnd().Replace("\n","").Split('\t');
	}

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
QuestionRyan PeschelView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Bryan JohnsonView Answer on Stackoverflow
Solution 3 - C#Steve DannerView Answer on Stackoverflow
Solution 4 - C#Andrew DennisonView Answer on Stackoverflow
Solution 5 - C#FidelView Answer on Stackoverflow
Solution 6 - C#Coding DuchessView Answer on Stackoverflow