C# StreamReader and StreamWriter Explained

In the last article we used the FileStream class to create a stream on a file to write/read byte data. We also used its Seek() method to seek in different positions in the stream. Today we are going to talk about the StreamReader and StreamWriter classes and how we can use them. StreamWriter is used to write characters to a file in specific encoding. The StreamReader is used to read characters, in specific encoding, from a file.

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 20
February 06, 2007
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

Recall from the last article (C# FileStream Explained) that the FileStream, MemoryStream and BufferedStream classes (as well as the Class NetworkStream) are all derived from the Stream class. But StreamReader and StreamWriter classes don't derive from the Stream Class. The StreamReader is derived from the abstract class TextReader, and StreamWriter is derived from the abstract class TextWriter. Note that both TextReader and TextWriter are derived from System.MarshalByRefObject which in turn is derived from System.Object.

My point is that StreamReader and StreamWriter don't extend the Stream base class or its descendant stream classes. So how they are used to write to files? Let's talk about that.

Both StreamWriter and StreamReader are used to write to/read from a stream in a specific encoding. this is illustrated using code in the following sections. Technically speaking, an instance of those classes is passed to a stream-based instance, a FileStream instance for example, that's used internally to write the bytes to the file. Or in another constructor overload you can pass a string path to the source file and a FileStream instance is created internally. Let's begin with an example that writes three lines to a file called aFile.txt

Using StreamWriter to write to a file

You can have a StreamWriter object as the return value from calling the method File.CreateText(). You can also create a StreamWriter object using one of its constructor overloads. The following example illustrates using a StreamWriter object with a FileStream object to write characters to the file aFile.txt

using System;
using System.IO;

namespace MyStreams
{
  class Class1
  {
    public static void Main()
    {
      try
      {
        FileStream fs = new FileStream
("aFile.txt",FileMode.Create,
        FileAccess.ReadWrite,FileShare.None);
        string[] strings = {"C#", "ASP.NET", "XML"};
        using(StreamWriter sw = new StreamWriter(fs))
        {
          Console.WriteLine("This StreamWriter instance uses {0}
to write to the file", sw.BaseStream);
          Console.WriteLine("The Property sw.Encoding returns:
{0}",sw.Encoding);
          sw.WriteLine("www.aspfree.com");
          sw.WriteLine("contains many useful articles");
          sw.WriteLine("on many different technologies like {0},
{1} and {2}", strings);
        }
        Console.WriteLine("Data has been written to the file");
        Console.ReadLine();
      }
      catch(IOException ex)
      {
        Console.WriteLine(ex.Message);
      }
    }
  }
}

Copy the above code and paste it in place of the auto-generated code of Class1.cs in your project, then run it and you will get the following screen shot:

Navigate to the folder of the application to open the file aFile.txt.

As you can see, there are three text lines written to this file. Let's walk through the code step-by-step

Step-by-step through the code example

The first statement in the try block is familiar, we just instantiate a new FileStream instance of the file aFile.txt with FileMode.Create and read/write access with exclusive access to this file. The next string array contains three string values that are used with the WriteLine() method, as we are going to see shortly.

We create a StreamWriter instance with the using statement to ensure that the StreamWriter.Close() instance method is called automatically. The constructor overload that we are using for this example accepts only one parameter which is the Stream that's used to interact with the source -- in other words the FileStream instance that is used to write to the file.

Calling the StreamWriter.Close() instance method explicitly or implicitly through the using statement ensures that the data is written to the associated stream object (which in our example is the fs instance) and calls the Close() method of the associated stream object.

The first Console.WriteLine() method prints out the value of the instance Property StreamWriter.BaseStream, which returns the stream that's associated with the StreamWriter instance, a FileStream instance. The second Console.WriteLine() method prints out the value of the instance Property StreamWriter.Encoding which returns UTF8 as the default encoding for the current StreamWriter instance.

After that we simply use the instance method StreamWriter.WriteLine() to write a line of characters to the file. Note that you can format the string value that's passed to this method, and that's what we have done in the third call to this method. Let's read from the file using the class StreamReader.

Using StreamReader to read from the file

In this example we use the StreamReader class to read the characters of the file aFile.txt in the following manner:

using System;
using System.IO;

namespace MyStreams
{
  class Class1
  {
    public static void Main()
    {
      try
      {
        FileStream fs = new FileStream("aFile.txt",
FileMode.OpenOrCreate, FileAccess.ReadWrite,FileShare.None);
        using(StreamReader sr = new StreamReader(fs))
        {
          // first solution
          //Console.WriteLine(sr.ReadToEnd());
          // second solution
          string temp;
          while((temp = sr.ReadLine()) != null)
          {
            Console.WriteLine(temp);
          }
        }
        Console.ReadLine();
      }
      catch(IOException ex)
      {
        Console.WriteLine(ex.Message);
      }
    }
  }
}

The result of running the above code example is illustrated in the above screen shot. We have read the contents of the file aFile.txt using an instance of the class StreamReader and by using the method ReadLine(). The instance method StreamReader.ReadLine() reads a line from the file and returns it as a string value, and if there are no more lines to read, it returns a null value.

In the above code we have created an instance of the StreamReader class and passed the the FileStream instance, which is used to interact with the source file. Then inside the using statement we create a variable of type string that's used in the while loop. The while loop's expression assigns the return value of calling the method ReadLine() of the StreamReader instance to the variable temp. The expression is evaluated to true if the value of the variable temp is not null, which means that a string that represents a line has been assigned to temp. Inside the while body we just print out the value of temp.

Note that I have commented another solution to return the contents of the file. Using the ReadToEnd() method returns a string that represents all the contents of the stream from the current position to the end of the stream. You can use it but please comment the solution that we have used after you remove the comment of the ReadToEnd() solution.

Encoding with the classes

In this example I'm going to show you how character encoding is handled with StreamWriter and StreamReader classes. Let's first look at the code example then discuss it.

using System;
using System.IO;
using System.Text;

namespace MyStreams
{
  class Class1
  {
    public static void Main()
    {
      try
      {
        FileStream fs = new FileStream("File1.txt",
FileMode.Create, FileAccess.ReadWrite);
        using(StreamWriter sw = new StreamWriter(fs))
        {
          sw.Write("h");
        }
        using(StreamWriter sw = new StreamWriter("File2.txt",
false,Encoding.UTF8))
        {
          sw.Write("h");
        }
        using(StreamWriter sw = new StreamWriter("File3.txt",false,Encoding.Unicode))
        {
          sw.Write("h");
        }
        using(StreamWriter sw = new StreamWriter("File4.txt",false,Encoding.BigEndianUnicode))
        {
          sw.Write("h");
        }

        // reading the bytes of the 4 files
        for(int i = 1; i < 5; i++)
        {
          string fileName = "File"+i+".txt";
          using(fs = new FileStream(fileName,FileMode.OpenOrCreate))
          {
            Console.WriteLine("nThe file {0} contains the following bytes: n", fileName);
            int temp;
            while((temp = fs.ReadByte()) != -1)
            {
              Console.Write(" {0} ", temp);
            }
          }
        }
        Console.ReadLine();
      }
      catch(IOException ex)
      {
        Console.WriteLine(ex.Message);
      }

    }
  }
}

Running the above code returns the bytes of every file as illustrated in the following screen shot:

Yes, we have written the letter "h" to the four files, but because StreamWriter can be used to write characters in UTF8, UTF7, Unicode and BigEndianUnicode encoding we got the above bytes written to the underlying FileStream instances. These in turn have written the bytes to the source files. If you are not familiar with Unicode I advise you to read an article about it, because you must know how the characters are encoded. The first statement in the try block creates a FileStream instance which is used by the first StreamWriter instance to write the letter "h" to the file.

As we said before, the default encoding for the StreamWriter is UTF8, but the StreamWriter instance's constructor overload that we have used doesn't write the BOM (Byte Order Mark). The next three using statements create three StreamWriters specifying the encoding used in the constructor. The second statement specifies UTF8 encoding to the constructor, which writes the Byte Order Mark 239 187 191 then the value of the character 'h' 104.

The third using statement specifies Unicode encoding which writes the Byte Order Mark 255 254, then the value of the Unicode 'h' as 104 0. The last using statement specifies BigEndianUnicode encoding which writes the Byte Order Mark 254 255 and the Unicode letter 'h' as 0 104.

Note that we have used the class Encoding of the namespace System.Text in order to specify the three encoding schemes that we need to use. I think that this example illustrate the usefulness of using the StreamWriter to write characters over the FileStream class.

blog comments powered by Disqus
C# ARTICLES

- Beginning C#
- ASP.NET RedirectPermanent Method using C# an...
- C Programming Language and UNIX Pioneer Pass...
- Using Facebook JavaScript SDK in ASP.NET wit...
- ASP.NET Export to Excel and Word using VB.NE...
- WAV and MP3 Streaming with ASP.Net and C#
- Game Programming using SDL: the File I/O API
- C# and Java Developer Jobs on the Rise
- The Future Evolution of C# and VB.NET
- C# If and Else-if Statements
- How To Use the C# String Replace Method
- 5 Ways to Parse XML in C#
- C# Meets Design Patterns
- Coding a CRC-Generating Algorithm in C
- Cyclic Redundancy Check

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 7 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials