C# Streams and File System Operations

C# Streams and File System Operations | Files, Directories & IO Tutorial

Working with data is a core part of many C# applications. Whether you are reading from files, writing logs, processing data in memory, or communicating over a network, C# provides a powerful and consistent way to handle input and output operations using Streams and file system APIs.

Streams represent a sequence of bytes that allow data to be read from or written to different sources, while file and directory classes enable you to create, access, manage, and organize data stored on the file system. Together, these features make C# well-suited for building efficient, secure, and scalable applications that interact with files and directories.

  1. C# - Stream
  2. Working with Files & Directories in C#
  3. C# - FileInfo

C# - Stream

C# includes following standard IO (Input/Output) classes to read/write from different sources like files, memory, network, isolated storage, etc.

Stream: System.IO.Stream is an abstract class that provides standard methods to transfer bytes (read, write, etc.) to the source. It is like a wrapper class to transfer bytes. Classes that need to read/write bytes from a particular source must implement the Stream class.

The following classes inherit Stream class to provide the functionality to Read/Write bytes from a particular source:

FileStream reads or writes bytes from/to a physical file, whether it is a .txt, .exe, .webp, or any other file. FileStream is derived from the Stream class.

MemoryStream: MemoryStream reads or writes bytes that are stored in memory.

BufferedStream: BufferedStream reads or writes bytes from other Streams to improve certain I/O operations' performance.

NetworkStream: NetworkStream reads or writes bytes from a network socket.

PipeStream: PipeStream reads or writes bytes from different processes.

CryptoStream: CryptoStream is for linking data streams to cryptographic transformations.

The following diagram shows the hierarchy of stream classes:

Stream Classes Hierarchy

Stream Readers and Writers

StreamReader: StreamReader is a helper class for reading characters from a Stream by converting bytes into characters using an encoded value. It can be used to read strings (characters) from different Streams like FileStream, MemoryStream, etc.

StreamWriter: StreamWriter is a helper class for writing a string to a Stream by converting characters into bytes. It can be used to write strings to different Streams such as FileStream, MemoryStream, etc.

BinaryReader: BinaryReader is a helper class for reading primitive datatype from bytes.

BinaryWriter: BinaryWriter writes primitive types in binary.

Stream IO

The above image shows that FileStream reads bytes from a physical file, and then StreamReader reads strings by converting those bytes to strings. In the same way, the StreamWriter takes a string and converts it into bytes and writes to the FileStream, and then the FileStream writes the bytes to a physical file. So, the FileStream deals with bytes, where as StreamReader and StreamWriter deals with strings.


Working with Files & Directories in C#

C# provides the following classes to work with the File system. They can be used to access directories, access files, open files for reading or writing, create a new file or move existing files from one location to another, etc.

Class Name Usage
File File is a static class that provides different functionalities like copy, create, move, delete, open for reading or /writing, encrypt or decrypt, check if a file exists, append lines or text to a file's content, get last access time, etc.
FileInfo The FileInfo class provides the same functionality as a static File class. You have more control on how you do read/write operations on a file by writing code manually for reading or writing bytes from a file.
Directory Directory is a static class that provides functionality for creating, moving, deleting and accessing subdirectories.
DirectoryInfo DirectoryInfo provides instance methods for creating, moving, deleting and accessing subdirectories.
Path Path is a static class that provides functionality such as retrieving the extension of a file, changing the extension of a file, retrieving the absolute physical path, and other path related functionalities.

File

C# includes static File class to perform I/O operation on physical file system. The static File class includes various utility method to interact with physical file of any type e.g. binary, text etc.

Use this static File class to perform some quick operation on physical file. It is not recommended to use File class for multiple operations on multiple files at the same time due to performance reasons. Use FileInfo class in that scenario.


Important Methods of Static File Class

Method Usage
AppendAllLines Appends lines to a file, and then closes the file. If the specified file does not exist, this method creates a file, writes the specified lines to the file, and then closes the file.
AppendAllText Opens a file, appends the specified string to the file, and then closes the file. If the file does not exist, this method creates a file, writes the specified string to the file, then closes the file.
AppendText Creates a StreamWriter that appends UTF-8 encoded text to an existing file, or to a new file if the specified file does not exist.
Copy Copies an existing file to a new file. Overwriting a file of the same name is not allowed.
Create Creates or overwrites a file in the specified path.
CreateText Creates or opens a file for writing UTF-8 encoded text.
Decrypt Decrypts a file that was encrypted by the current account using the Encrypt method.
Delete Deletes the specified file.
Encrypt Encrypts a file so that only the account used to encrypt the file can decrypt it.
Exists Determines whether the specified file exists.
GetAccessControl Gets a FileSecurity object that encapsulates the access control list (ACL) entries for a specified file.
Move Moves a specified file to a new location, providing the option to specify a new file name.
Open Opens a FileStream on the specified path with read/write access.
ReadAllBytes Opens a binary file, reads the contents of the file into a byte array, and then closes the file.
ReadAllLines Opens a text file, reads all lines of the file, and then closes the file.
ReadAllText Opens a text file, reads all lines of the file, and then closes the file.
Replace Replaces the contents of a specified file with the contents of another file, deleting the original file, and creating a backup of the replaced file.
WriteAllBytes Creates a new file, writes the specified byte array to the file, and then closes the file. If the target file already exists, it is overwritten.
WriteAllLines Creates a new file, writes a collection of strings to the file, and then closes the file.
WriteAllText Creates a new file, writes the specified string to the file, and then closes the file. If the target file already exists, it is overwritten.

Append Text Lines

Use AppendAllLines() method to append multiple text lines to the specified file as shown below.

Example: Append all text lines to a file
string dummyLines = "This is first line." + Environment.NewLine +
                    "This is second line." + Environment.NewLine +
                    "This is third line.";

//Opens DummyFile.txt and append lines. If file is not exists then create and open.
File.AppendAllLines(@"C:DummyFile.txt", dummyLines.Split(Environment.NewLine.ToCharArray()).ToList<string>());

Append String

Use File.AppendAllText() method to append string to a file in single line of code as shown below.

Example: Append string to a file
//Opens DummyFile.txt and append Text. If file is not exists then create and open.
File.AppendAllText(@"C: DummyFile.txt", "This is File testing");
</code></pre>
            <div className="card-footer example-footer"></div>     </div>
    </div>
    <h2>Overwrite Text</h2>
    <p>Use <i>File.WriteAllText()</i> method to write texts to the file. Please note that it will not append text but overwrite existing texts.</p>
    <div className="card code-panel">
        <div className="card-header example-title">Example: Overwrite existing texts</div>
        <div className="panel-body">
            <pre className="csharpcode">
<code>//Opens DummyFile.txt and write texts. If file is not exists then create and open.
File.WriteAllText(@"C:DummyFile.txt", "This is dummy text");

The following example shows how to perform different operations using static File class.

Example: Multiple File operations
//Check whether file is exists or not at particular location
bool isFileExists = File.Exists(@"C: DummyFile.txt"); // returns false

//Copy DummyFile.txt as new file DummyFileNew.txt
File.Copy(@"C:DummyFile.txt", @"D:NewDummyFile.txt");

//Get when the file was accessed last time 
DateTime lastAccessTime = File.GetLastAccessTime(@"C:DummyFile.txt");

//get when the file was written last time
DateTime lastWriteTime = File.GetLastWriteTime(@"C:DummyFile.txt");

// Move file to new location
File.Move(@"C:DummyFile.txt", @"D:DummyFile.txt");

//Open file and returns FileStream for reading bytes from the file
FileStream fs = File.Open(@"D:DummyFile.txt", FileMode.OpenOrCreate);

//Open file and return StreamReader for reading string from the file
StreamReader sr = File.OpenText(@"D:DummyFile.txt");
    
//Delete file
File.Delete(@"C:DummyFile.txt");

Thus, it is easy to work with physical file using static File class. However, if you want more flexibility then use FileInfo class. The same way, use static Directory class to work with physical directories.

Visit MSDN to know all the methods of the static File class.


C# - FileInfo

Here, you will learn how to use FileInfo class to perform read/write operation on physical files.

The FileInfo class provides the same functionality as the static File class but you have more control on read/write operations on files by writing code manually for reading or writing bytes from a file.


Important Properties and Methods of FileInfo:

Property Usage
Directory Gets an instance of the parent directory.
DirectoryName Gets a string representing the directory's full path.
Exists Gets a value indicating whether a file exists.
Extension Gets the string representing the extension part of the file.
FullName Gets the full path of the directory or file.
IsReadOnly Gets or sets a value that determines if the current file is read only.
LastAccessTime Gets or sets the time the current file or directory was last accessed
LastWriteTime Gets or sets the time when the current file or directory was last written to
Length Gets the size, in bytes, of the current file.
Name Gets the name of the file.
Method Usage
AppendText Creates a StreamWriter that appends text to the file represented by this instance of the FileInfo.
CopyTo Copies an existing file to a new file, disallowing the overwriting of an existing file.
Create Creates a file.
CreateText Creates a StreamWriter that writes a new text file.
Decrypt Decrypts a file that was encrypted by the current account using the Encrypt method.
Delete Deletes the specified file.
Encrypt Encrypts a file so that only the account used to encrypt the file can decrypt it.
GetAccessControl Gets a FileSecurity object that encapsulates the access control list (ACL) entries for a specified file.
MoveTo Moves a specified file to a new location, providing the option to specify a new file name.
Open Opens a in the specified FileMode.
OpenRead Creates a read-only FileStream.
OpenText Creates a StreamReader with UTF8 encoding that reads from an existing text file.
OpenWrite Creates a write-only FileStream.
Replace Replaces the contents of a specified file with the file described by the current FileInfo object, deleting the original file, and creating a backup of the replaced file.
ToString Returns a path as string.

The following example shows how to read bytes from a file manually and then convert them to a string using UTF8 encoding:

Example: Read file using FileInfo class

//Create object of FileInfo for specified path           
FileInfo fi = new FileInfo(@"D:DummyFile.txt");

//Open file for Read-Write
FileStream fs = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); 

//create byte array of same size as FileStream length
byte[] fileBytes = new byte[fs.Length];

//define counter to check how much bytes to read. Decrease the counter as you read each byte
int numBytesToRead = (int)fileBytes.Length;

//Counter to indicate number of bytes already read
<span className="kwrd">int</span> numBytesRead = 0;

//iterate till all the bytes read from FileStream
while (numBytesToRead &gt; 0)
{
    int n = fs.Read(fileBytes, numBytesRead, numBytesToRead);
        
    if (n == 0)
        break;

    numBytesRead += n;
    numBytesToRead -= n;
}

//Once you read all the bytes from FileStream, you can convert it into string using UTF8 encoding
string filestring = Encoding.UTF8.GetString(fileBytes);

As you have seen in the above code, you have to write lot of code for reading/writing a string from a FileSream. The same read/write operation can be done easily using StreamReader and StreamWriter.

The following example shows how StreamReader makes it easy to read strings from a file:

Example: Read file using StreamReader

        //Create object of FileInfo for specified path           
FileInfo fi = new FileInfo(@"D:DummyFile.txt");
        
//Open file for ReadWrite
FileStream fs = fi.Open(FileMode.OpenOrCreate, FileAccess.Read , FileShare.Read); 

//Create object of StreamReader by passing FileStream object on which it needs to operates on
StreamReader sr = new StreamReader(fs);

//Use ReadToEnd method to read all the content from file
<span className="kwrd">string</span> fileContent = sr.ReadToEnd();

//Close StreamReader object after operation
sr.Close();
fs.Close();

Notice that fi.Open() has three parameters: The first parameter is FileMode for creating and opening a file if it does not exist; the second parameter, FileAccess, is to indicate a Read operation; and the third parameter is to share the file for reading with other users while the file is open.

The following example shows how StreamWriter makes it easy to write strings to a File:

Example: Write texts to file using StreamWriter

        //Create object of FileInfo for specified path           
FileInfo fi = new FileInfo(@"D:DummyFile.txt");
        
//Open file for ReadWrite
FileStream fs = fi.Open(FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read ); 

//Create StreamWriter object to write string to FileSream
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("Another line from streamwriter");
sw.Close();

Read and Write operations are not possible on the same FileStream object simultaneously. If you are already reading from a file, create a separate FileStream object to write to the same file, as shown below:

Example: StreamReader & StreamWriter

        //Create FileInfo object for DummyFile.txt
FileInfo fi = new FileInfo(@"D:DummyFile.txt");

//open DummyFile.txt for read operation
FileStream fsToRead = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite , FileShare.ReadWrite); 

//open DummyFile.txt for write operation
FileStream fsToWrite = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); 
          
//get the StreamReader
StreamReader sr = new StreamReader(fsToRead);
//read all texts using StreamReader object
string fileContent = sr.ReadToEnd();
sr.Close();

//get the StreamWriter
StreamWriter sw = new StreamWriter(fsToWrite);
//write some text using StreamWriter
sw.WriteLine("Another line from streamwriter");
sw.Close();

//close all Stream objects
fsToRead.Close();
fsToWrite.Close();

Thus you can use FileInfo, StreamReader and StreamWriter class to read/write contents from physical file.

Sandip Mhaske

I’m a software developer exploring the depths of .NET, AWS, Angular, React, and digital entrepreneurship. Here, I decode complex problems, share insightful solutions, and navigate the evolving landscape of tech and finance.

Post a Comment

Previous Post Next Post