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.
StreamReader is designed for character input in a particular encoding, whereas the Stream class is designed for byte input and output. Use StreamReader for reading lines of information from a standard text file. Important. This type implements the IDisposable interface.
Open(FileMode. OpenOrCreate, FileAccess. Read , FileShare. Read); //Create an object of StreamReader by passing FileStream object on which it needs to operates on StreamReader sr = new StreamReader(fs); //Use the ReadToEnd method to read all the content from file string fileContent = sr.
Specifically, a FileStream exists to perform reads and writes to the file system. Most streams are pretty low-level in their usage, and deal with data as bytes. A StreamWriter is a wrapper for a Stream that simplifies using that stream to output plain text.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With