Home > C# .NET > C# .NET Tutorial 6: Reading and Writing Files

C# .NET Tutorial 6: Reading and Writing Files

In the last couple of week I have been writing a number of C# tutorials. This is number 6 and today we will discuss reading and writing of files, two very common tasks in development. For those who are new the previous 5 tutorials can be found here.

Streams

Streams are used to write and read both sequential and random access data. These are the common properties of the Stream class in .NET:

  • CanRead – determines whether stream supports reading.
  • CanSeek – determines whether stream supports seeking.
  • CanTimeout – determines whether stream supports time out.
  • CanWrite – determines whether stream supports writing.
  • Length – returns the length in bytes of the stream.
  • Position – gets or sets the cursor to determine where in the stream the current position is.
  • ReadTimeout – gets or sets the stream’s time out for read operations.
  • WriteTimeout – gets or sets the stream’s time out for write operations.

The following are the Stream common methods:

  • Close – closes the stream and releases any associated resources with it.
  • Flush – clears any buffers within the stream and forces any changes to the stream to be written to the underlying system or device represented by the stream.
  • Read – performs a sequential read from the current position of a number of bytes and updates the position to the end of the read bytes.
  • ReadByte – reads one byte and updates the position by one.
  • Seek – sets the position within the stream.
  • SetLength – specifies the length of the stream.
  • Write – writes information to the stream as number of bytes and updates the current position to reflect the new write position.
  • WriteByte – writes a single byte to the stream and updates the position by one.

All the stream classes in .NET derive from the Stream class. These include:

  • FileStream (System.IO)
  • MemoryStream (System.IO)
  • CryptoStream (System.Security)
  • NetworkStream (System.Net)
  • GZipStream (System.Compression)

The reason these streams have the same base class is that working with data as a flow is a common way in different scenarios. Let’s start looking at some examples how to work with a stream. Learning to work with a stream means that you can apply that knowledge to any type of stream. To dump the contents of a stream on screen you use the following code:

//make sure we read from the beginning
theStream.Position = 0;
//Go through the entire stream and read byte by byte
while (theStream.Position != theStream.Length)
{
    Console.WriteLine("{0:x2}", theStream.ReadByte());
}

This code is able to work on any kind of stream. The next example is to send information to a stream:

theStream.Position = theStream.Length; //puts cursor at the end
theStream.Write(data, 0 , data.Length);

Classes for Reading and Writing data

A number of classes take part in the process of reading and writing files. One of these is the File class. This classes exposes static methods used for opening and creating classes. The File class can perform:

  • Atomic operations to read and write to files.
  • Operations to open files for reading or writing.
  • Simple file operations (File.Exists, File.Delete, etc.).

The File class can return a number of types with the FileStream being the most rudimentary. The File Class also has methods that return objects of type StreamReader and StreamWriter.These classes wrap a FileStream to support sequential reading and writing to a stream.

The File operations supported by the File Class are the same as the FileInfo class.

The MemoryStream is a special stream for manipulating data in memory. This stream is used to create stream objects in memory for optimization.

File Class

The File class is used to handle file streams for reading and writing. These are the most important File static methods:

  • AppendAllText – appends a string to a file. If the file does not exist it creates it.
  • AppendText – Opens a file and returns a StreamWriter that is prepared to allow text to be added to the file.
  • Copy – copies a file to a new file. The new file must not exist for Copy to be successful.
  • Create – creates a new file and returns a FileStream.
  • CreateText – creates or opens a file and returns a StreamWriter ready to have text written to it.
  • Move – moves a file from one place to another.
  • Open – opens an existing file and returnsĀ  FileStream object.
  • OpenRead – opens an existing file and returns a read-only FileStream object.
  • OpenText – opens an existing file and returns a StreamReader object.
  • OpenWrite – opens an existing file for writing and returns a StreamWriter object.
  • ReadAllBytes – opens a file, reads the content to a byte array, and closes the file in one atomic operation.
  • ReadAllLines – opens a file, reads the content line by line into an array of strings and closes the file in one atomic operation.
  • ReadAllText – opens a file, reads the content into a string, and closes the file in one atomic operation.
  • WriteAllBytes – opens a file, writes the content of a byte array in it, and closes the file in one atomic operation.
  • WriteAllLines – opens a file, writes the content from an array of strings into the file, and closes the file in one atomic operation.
  • WriteAllText – opens a file, writes the content into a string, and closes the file in one atomic operation.

Directory Class

Like the File class, the Directory class has a number of static methods to manipulate and create directories. These are the most important methods:

  • CreateDirectory – creates all directories in a supplied path.
  • Delete – deletes a specified directory.
  • Exists – determines whether a directory exists or not.
  • GetCreationTime – returns the time and date of creation of a directory.
  • GetCurrentDirectory – returns a DirectoryInfo object for the current working directory of the application.
  • GetDirectories – gets a list of names for subdirectories of a directory specified.
  • GetDirectoryRoot – returns the volume or root information for a specified directory.
  • GetFiles – returns the names of files in a directory.
  • GetFileSystemEntries – returns a list of files and subdirectories for a specified directory.
  • GetLastAccessTime – returns the time that a directory was last accessed.
  • GetLastWriteTime – returns the time that a specified directory was last written to.
  • GetLogicalDrives – creates a list of drives as strings in the format “C:\”.
  • GetParent – gets the parent directory of the specified directory.
  • Move – moves a file or directory to a specified place.
  • SetCreationTime – sets the time a specified directory was created.
  • SetCurrentDirectory – sets a specified directory to be the current working directory for the application.
  • SetLastAccessTime – sets the last time a directory was accessed.
  • SetLastWriteTime – sets the last time a directory was written to.

FileAccess Enumeration

The FileAccess enumeration provides members that are used to determine the access rights required when opening a file. These are:

  • Read
  • Write
  • ReadWrite

FileMode Enumeration

The FileMode Enumeration specifies how a file should be opened or created. These are:

  • Append – opens a file and moves the pointer in the FileStream object at the end. Can only be used with FileAccess.Write.
  • Create – creates a new file. If it exists it is overwritten.
  • CreateNew – creates a new file. If the file exists then it throws an exception.
  • Open – open an existing file. If the file does not exist, an exception is thrown.
  • OpenOrCreate – opens an existing file. If the file does not exist, it creates a new file.
  • Truncate – opens an existing file but empties the file so that it is zero bytes long.

FileStream Class

The FileStream class provides the functionality to open file streams for reading and writing. These are the most important methods:

  • CanRead – determines whether stream supports reading.
  • CanSeek – determines whether the stream supports seeking.
  • CanTimeout – determines whether the stream can time out.
  • CanWrite – determines whether the stream can write.
  • Handle – gets the stream’s underlying file handle.
  • Length – gets the length (bytes) of the stream.
  • Name – gets the name of the file.
  • Position – gets or sets the virtual cursor for determining where in the stream the current position is.
  • ReadTimeout – gets or sets the stream’s timeout for read operations.
  • WriteTimeout – gets or sets the stream’s timeout for write operations.
  • Close – closes the stream and releases any associated resources.
  • Flush – clears any buffers within the stream and forces any changes to be written to the underlying system or device.
  • Lock – prevents other processes from changing part of the file.
  • Read – performs a sequential read of a specified number of bytes and updates the position of the cursor accordingly.
  • ReadByte – performs a read of a single byte and updates the position of the cursor by one.
  • Seek – sets the position within the stream.
  • SetLength – specifies the length of the stream.
  • Unlock – lets other processes change the stream.
  • Write – writes sequentially a specified number of bytes and moves the cursor at the end.
  • WriteByte – writes one byte to the stream and moves the cursor one position.

StreamReader Class

The StreamReader class provides the functionality to read data from a Stream derived class. These are the important properties:

  • BaseStream – gets the underlying stream that the reader is reading.
  • CurrentEncoding – gets the current encoding used by the stream.
  • EndOfStream – determines whether the reader has encountered the end of the stream.

These are the most commonly used methods:

  • Close – closes the reader and the underlying stream.
  • Peek – returns the next character in the stream without moving the cursor.
  • Read – reads the next set of characters from the stream.
  • ReadBlock – reads the next block of characters from the stream.
  • ReadLine – reads the next line of characters in the stream.
  • ReadToEnd – reads all the characters through to the end of the stream.

How to Read a File in C#

Here is the code to open a file and read from it.

//first open the file
FileStream theFile = File.Open(@"C:\test.txt", FileMode.Open, FileAccess.Read);

//the File.Open returns a FileStream. We will create StreamReader that wraps the FileStream.
StreamReader reader = new StreamReader(theFile);

Console.WriteLine(reader.ReadToEnd());

//close reader and stream
reader.Close();
theFile.Close();

It is important to note that the StreamReader returns data as a string. The File class has additional methods that make it simpler to open a file for reading. The File class supports creating a StreamReader immediately without the need of wrapping a FileStream. This is done as follows.

StreamReader reader = File.Open(@"C:\test.txt");
Console.WriteLine(reader.ReadToEnd());
reader.Close();

If you want to read the whole file at one go then it can become even simpler as follows.

Console.WriteLine(File.ReadAllText(@"C:\test.txt"));

The last example shows code that is looking inside a file and finding a particular word (“test”).

StreamReader reader = File.Open(@"C:\test.txt");

while (!reader.EndOfStream)
{
    string line = reader.ReadLine();
    if (line.Contains("test"))
    {
        Console.WriteLine("Found test");
        break;
    }
}

StreamWriter Class

The StreamWriter class provides the functionality to write data to streams. The following are its important properties:

  • AutoFlush – gets or sets an indicator that shows whether every call to the Write method should flush changes to the underlying stream.
  • BaseStream – gets the underlying stream that the writer is writing.
  • Encoding – gets the encoding the underlying stream is using.
  • NewLine – gets or sets a string that contains the line terminator string. This is used only if you want to change the string that terminates every individual line.

The following are the most commonly used methods:

  • Close – closes the writer and the underlying stream.
  • Write – writes to the stream.
  • WriteLine – writes data to the stream followed by a string that terminates each individual line.

How to Write to a File in C#

The following is the code used to write to a file in C#.

StreamWriter writer = File.CreateText(@"C:\test.txt");
writer.WriteLine("Test");
writer.Close();

The StreamWriter can also write a chunk of text all at once.

File.WriteAllText(@"C:\test.txt", "Test1 Test2");

If you want to write to an existing file you use the follow code.

FileStream stream = File.OpenWrite(@"C:\test.txt");
StreamWriter writer = new StreamWriter(stream);
writer.Write("Hello World!");
writer.Close();
stream.Close();

Finally if you do not know whether a file exists or not but if it exists you want to append you use the following code.

FileStream stream = File.Open(@"C:\test.txt", FileMode.OpenCreate, FileAccess.Write);
StreamWriter writer = new StreamWriter(stream);
writer.Write("Hello World!");
writer.Close();
stream.Close();

Understanding Readers and Writers

The StreamReader and StreamWriter classes inherit from the TextReader and TextWriter abstract classes respectively. There are other readers and writers. These are:

  • StringReader/StringWriter – read to and write from in-memory strings.
  • BinaryReader/BinaryWriter – used to handle getting binary data to and from streams.

MemoryStream Class

This class provides the functionality to create in-memory streams. The following are the most important properties:

  • CanRead – determines whether the stream supports reading.
  • CanWrite – determines whether the stream supports writing.
  • CanSeek – determines whether the stream supports seeking.
  • CanTimeout – determines whether the stream can time out.
  • Capacity – gets or sets the number of bytes allocated for the stream.
  • Length – gets the length (in bytes) of the stream.
  • Position – gets or sets the position of the cursor in the stream.
  • ReadTimeout – gets or sets the time out for the read operation of the stream.
  • WriteTimeout – gets or sets the time out for the write operation of the stream.

These are the main MemoryStream methods:

  • Close – closes the stream and releases any resources associated with it.
  • Flush – clears any buffers within the stream and forces changes to be written to the underlying system or device.
  • GetBuffer – retrieves the array of unsigned bytes that was used to create the stream.
  • Read – performs a sequential read of a specified number of bytes and updates the position of the cursor.
  • ReadByte – reads a byte and moves the cursor position by one.
  • Seek – sets the position within the stream.
  • SetLength – specifies the length of the stream.
  • ToArray – writes the entire stream to an array of bytes.
  • Write – writes a number of specified bytes to the stream and updates the cursor accordingly.
  • WriteByte – writes a byte of data into the stream and moves the cursor one position.
  • WriteTo – writes the MemoryStream to another stream.

How to Use the Memory Stream

Here is an example how to use the MemoryStream and then write it to a FileStream.

MemoryStream memStream = new MemoryStream();
StreamWriter writer = new StreamWriter(memStream);
writer.WriteLine("Hello World");
//force the writer to push the data in the stream
writer.Flush();

FileStream theFile = File.Create(@"C:\test.txt");
memStream.WriteTo(theFile);
writer.Close();
theFile.Close();
memStream.Close();

The BufferedStream Class

The BufferedStream Class provides the basic functionality to wrap streams to improve performance by buffering reads and writes to the stream. Its most important properties and methods are the same as the MemoryStream.

How to use a BufferedStream

The BufferedStream should be used in situations when writing out data to a stream directly does not perform well. The following code demonstrates how to use a BufferedStream.

FileStream theFile = File.Create(@"C:\test.txt");
BufferedStream buffer = new BufferedStream(theFile);
StreamWriter writer = new StreamWriter(buffer);
writer.WriteLine("Hello");
writer.Close();

Well for today that is enough. In the next tutorial we will take a look at Compressed Streams. Until then bye bye!

About these ads
Categories: C# .NET
  1. September 9, 2010 at 11:50 am | #1

    Thank you
    My blog http://www.e-projects.co.cc/

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: