[C# – I/O] Streams and Files

File IO is a basic task, which every developer needs to know. In C#, Streams are used to read/write data from/to a file. Streams are generic representation of data flow. They are not restricted to files. Using streams, you can access data from many different sources (such as memory) in the same manner. Stream related classes are usually located within the “System.IO” namespace.

 

1. Streams and IDispose

In general, streams exist in pairs. (one for reading, another for writing). You open a stream, read/write data from/to the stream, and close the stream. As you already know, closing a stream is really important. But any stream operations might cause exceptions from various reasons, therefore you need to enclose a code block in a “try/catch” and close the stream in the “finally” block.

The better way is the “using” block. All streams implements “IDispose” interface and the “using” block ensures that the stream is closed at any rate.

 

2. Text Files – TextReader/TextWriter

The most basic streams for text files are “System.IO.TextReader” and “System.IO.TextWriter“. Both classes are abstract classes, therefore you cannot create objects directly.

These classes provides basic methods to access text files.

– Read methods of TextReader

  • int Read(): reads the next character
  • int Read(char[] buffer, int index, int count): reads a maximum of count characters beginning at index; returns the number of characters that have been read
  • string ReadLine(): reads a line of characters
  • string ReadToEnd(): reads all characters from the current position to the end

– Write methods of TextWriter

  • void Write(type value)
  • void WriteLine(type value)

There are a lot of overloaded versions of “Write” and “WriteLine” methods for various data types.

 

3. Text Files – StreamReader/StreamWriter

When you work with text files, the “System.IO.StreamReader” and “System.IO.StreamWriter” classes are used in general. You can create stream objects using constructors or the static methods of the “System.IO.File” class.

The “System.IO.File” class provides the “OpenText()” and “CreateText()” methods.

  • static StreamReader OpenText(string path): opens an existing UTF-8 encoded text file for reading
  • static StreamWriter CreateText(string path): creates or opens a file for writing UTF-8 encoded text

The default encoding is “UTF-8” and if you are using different encoding, you need to pass it to the stream constructors.

The StreamReader/StreamWriter classes are derived from the TextReader/TextWriter classes and used for sequential accessing.

public static void TestFileIO()
{
  string filePath = @"C:/temp/test.txt";
  if (File.Exists(filePath))
  {
    File.Delete(filePath);
  }

  using (StreamWriter sw = File.CreateText(filePath))
  {
    sw.WriteLine("Hello, World");
    sw.WriteLine("This is a test.");
  }

  using (var sr = new StreamReader(filePath))
  {
    string inputStr;
    while ((inputStr = sr.ReadLine()) != null)
    {
      Console.WriteLine(inputStr);
    }
  }
}

 

4. FileStream

The “System.IO.FileStream” is used for both reading and writing. It also supports random access.

When opening a file using “FileStream“, you can pass the “FileMode” and “FileAccess” enum values:

  • FileMode: CreateNew, Create, Open, OpenOrCreate, Truncate, Append
  • FileAccess: Read, Write, or ReadWrite.

– Methods –

  • long Seek(long offset, SeekOrigin origin): sets the current position
  • int Read(byte[] array, int offset, int count)
  • int ReadByte()
  • Write(byte[] array, int offset, int count)
  • void WriteByte(byte value)

By using the “Seek” method, you can access the file randomly. The  “SeekOrigin” enum can be “Begin”, “Current”, or “End”.

 

5. Binary Files – BinaryReader/BinaryWriter

The “StreamReader” and “StreamWriter” are used to access text files. For binary files, “BinaryReader” and “BinaryWriter” are used. They are usually used with “FileStream” as a base stream.

The “BinaryReader” prvodes “Read—()” methods and the “BinaryWriter” provides “Write(—)” methods.

public static void TestBinaryFileIO()
{
  string filePath = @"C:/temp/testbinary.test";
  if (File.Exists(filePath))
  {
    File.Delete(filePath);
  }

  using (var fsw =
    new FileStream(filePath, FileMode.Create, FileAccess.Write))
  {
    using (var bw = new BinaryWriter(fsw))
    {
      bw.Write("Homer Simpson");
      bw.Write(36);
    }
  }

  using (var fsr =
    new FileStream(filePath, FileMode.Open, FileAccess.Read))
  {
    using (var br = new BinaryReader(fsr))
    {
      Console.WriteLine("Name: {0}", br.ReadString());
      Console.WriteLine("Age: {0}", br.ReadUInt32());
    }
  }
}
This entry was posted in C# and tagged . Bookmark the permalink.

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s