It’s time to learn how to work with files in C#. For that purpose, in this article, we will cover two classes StreamWriter and StreamReader.

For the complete navigation of this series check out: C# Back to Basics.

If you want to download the source code for our examples, you can do that from here StreamWriter and StreamReader C# Source Code.

The StreamReader and StreamWriter classes enable the reading and writing actions to a file. Both of these classes exist in the System.IO namespace as well as many other classes for working with files and directories.

We are going to cover the following sections:

Creating Objects for StreamWriter and StreamReader

To create objects for the StreamReader and StreamWriter classes we need to use the standard initialization for the reference data types. We can execute this initialization in a couple of ways but the most common is by only providing an address to the file:

As we can see from the code above, we can provide the relative or absolute path to our file. If we provide a relative path (just a name and extension) Visual Studio will place a file inside the projectName/bin/debug folder.

StreamReader Methods

StreamReader contains many different methods to work with files but we are going to mention few of those.

The Read() method will return next sign as an integer number or -1 if we reached the end of the file. We can use explicit conversion (cast) to convert that integer into a char type:

The ReadLine() method will return a whole line as a string. If we reached the end of the file it will return null:

The ReadToEnd() method returns a whole file in one string. If there is nothing more to read it will return an empty string.

The Peek() method checks the next character in the file or if it finds nothing it will return -1:

StreamWriter Methods

The two most important methods for the StreamWriter class is the Write() and WriteLine(). With the Write() method we write a line inside a file but without moving to another line after. But with the WriteLine() method we write a line inside a file and moving to another line.

It is very important to call the Close() method, after we are finished with using reader or writer objects.

Example1: Create an application that writes five random numbers from 1 to 100 to a file named numbers.txt. Then it will read all the numbers from that file, print them out and print the maximum number:

As we can see, we have to use the Close method to close our reader and writer. But there is an even better way to do this. By using the using block.

Using Block

The using block helps to manage our resources. It specifies a scope in which we use our resource, and once we leave that scope, the resource is going to be managed.

To use the using block we need to specify the using keyword, create resources inside parentheses and declare the scope of the using block with the curly brackets:

So, we can rewrite one of our methods form the previous example:

In this example, we are not using the Close method because as soon as execution leaves the body of the using statement, the StreamReader object is going to be managed.


There we go. Right now, we have a good knowledge to manipulate files from C#.

In the next article, we are going to learn how to use File and Directory classes to manipulate files in C#.

If you have enjoyed reading this article and if you would like to receive the notifications about the freshly published .NET Core content we encourage you to subscribe to our blog.