C# – FileStream StreamReader problem in C#

c++

I'm testing how the classes FileStream and StreamReader work togheter. Via a Console application.
I'm trying to go in a file and read the lines and print them on the console.

I've been able to do it with a while-loop, but I want to try it with a foreach loop.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace testing
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string file = @"C:\Temp\New Folder\New Text Document.txt";
            using(FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                using(StreamReader sr = new StreamReader(fs))
                {
                    foreach(string line in file)
                    {
                        Console.WriteLine(line);
                    }
                }
            }
        }
    }
}

The error I keep getting for this is: Cannot convert type 'char' to 'string'

The while loop, which does work, looks like this:

while((line = sr.ReadLine()) != null)
{
    Console.WriteLine(line);
}

I'm probably overlooking something really basic, but I can't see it.

Best Solution

If you want to read a file line-by-line via foreach (in a reusable fashion), consider the following iterator block:

    public static IEnumerable<string> ReadLines(string path)
    {
        using (StreamReader reader = File.OpenText(path))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                yield return line;
            }
        }
    }

Note that this this is lazily evaluated - there is none of the buffering that you would associate with File.ReadAllLines(). The foreach syntax will ensure that the iterator is Dispose()d correctly even for exceptions, closing the file:

foreach(string line in ReadLines(file))
{
    Console.WriteLine(line);
}

(this bit is added just for interest...)

Another advantage of this type of abstraction is that it plays beautifully with LINQ - i.e. it is easy to do transformations / filters etc with this approach:

        DateTime minDate = new DateTime(2000,1,1);
        var query = from line in ReadLines(file)
                    let tokens = line.Split('\t')
                    let person = new
                    {
                        Forname = tokens[0],
                        Surname = tokens[1],
                        DoB = DateTime.Parse(tokens[2])
                    }
                    where person.DoB >= minDate
                    select person;
        foreach (var person in query)
        {
            Console.WriteLine("{0}, {1}: born {2}",
                person.Surname, person.Forname, person.DoB);
        }

And again, all evaluated lazily (no buffering).

Related Question