C# - StreamReader and StreamWriter

'StreamReader' and 'StreamWriter' are classes in C# that provide convenient ways to read from and write to files, respectively. They are part of the 'System.IO' namespace and are commonly used for file I/O operations.

1. StreamReader:
'StreamReader' is used to read text from a file. It allows you to read characters, lines, or the entire content of a text file easily.

Example of using 'StreamReader' to read from a file:


using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "example.txt";

        // Read text from the file using StreamReader
        using (StreamReader reader = new StreamReader(filePath))
        {
            // Read a single line from the file
            string line = reader.ReadLine();
            Console.WriteLine("First line: " + line);

            // Read the entire content of the file
            string content = reader.ReadToEnd();
            Console.WriteLine("File Content:\n" + content);
        }
    }
}

2. StreamWriter:
'StreamWriter' is used to write text to a file. It allows you to create a new file or overwrite an existing one, and you can write text either as a single string or line by line.

Example of using 'StreamWriter' to write to a file:


using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "output.txt";

        // Write text to the file using StreamWriter
        using (StreamWriter writer = new StreamWriter(filePath))
        {
            writer.WriteLine("Hello, this is the first line.");
            writer.WriteLine("And this is the second line.");
            writer.Write("This is the third line.");
        }
    }
}

2. 'StreamWriter' and 'Append' Mode:
You can also use 'StreamWriter' with the 'Append' mode to add content to an existing file without overwriting its previous content.

Example of using 'StreamWriter' with 'Append' mode:


using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "log.txt";

        // Write log entries to the file using StreamWriter in append mode
        using (StreamWriter writer = new StreamWriter(filePath, append: true))
        {
            writer.WriteLine($"[{DateTime.Now}] Error: Something went wrong.");
            writer.WriteLine($"[{DateTime.Now}] Info: Operation completed successfully.");
        }
    }
}

In this example, the 'StreamWriter' is constructed with append: true, which ensures that new content will be added to the end of the file without overwriting the existing content.

Both 'StreamReader' and 'StreamWriter' are wrapped in a using statement to ensure that the resources are properly disposed of when they are no longer needed.

In summary, 'StreamReader' and 'StreamWriter' are powerful classes for reading and writing text files in C#. They provide a simple and efficient way to work with files and are often used in various file I/O scenarios in C# applications.

Closing and disposing of stream readers and writers

Closing and disposing of stream readers and writers are essential to ensure proper resource management and prevent resource leaks. Both 'StreamReader' and 'StreamWriter' implement the 'IDisposable' interface, which means they have a 'Dispose()' method. You should wrap instances of these classes in a using statement to automatically call the 'Dispose()' method when they go out of scope.

1. Closing and Disposing of 'StreamReader':

Example of using 'StreamReader' with the using statement:


using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "example.txt";

        // Read text from the file using StreamReader
        using (StreamReader reader = new StreamReader(filePath))
        {
            // Read lines one by one
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }
        } // StreamReader is automatically disposed here (closed as well)
    }
}

2. Closing and Disposing of 'StreamWriter':

Example of using 'StreamWriter' with the 'using' statement:


using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "output.txt";

        // Write text to the file using StreamWriter
        using (StreamWriter writer = new StreamWriter(filePath))
        {
            writer.WriteLine("Hello, this is the first line.");
            writer.WriteLine("And this is the second line.");
            writer.Write("This is the third line.");
        } // StreamWriter is automatically disposed here (closed as well)
    }
}

Reading and Writing Line by Line

When working with large files, it's generally more memory-efficient to read or write line by line instead of loading the entire file content into memory. This approach is particularly useful when dealing with log files, data processing, or file transformation.

Example of reading and writing line by line:


using System;
using System.IO;

class Program
{
    static void Main()
    {
        string sourceFilePath = "source.txt";
        string destinationFilePath = "destination.txt";

        // Read lines from the source file and write them to the destination file
        using (StreamReader reader = new StreamReader(sourceFilePath))
        using (StreamWriter writer = new StreamWriter(destinationFilePath))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                // Process the line if needed (e.g., modify, filter, etc.)
                string processedLine = ProcessLine(line);

                // Write the processed line to the destination file
                writer.WriteLine(processedLine);
            }
        } // Both StreamReader and StreamWriter are automatically disposed here (closed as well)
    }

    static string ProcessLine(string line)
    {
        // Add your custom logic to process the line here
        return line.ToUpper(); // Example: convert the line to uppercase
    }
}

In this example, the 'ProcessLine' method can be used to modify or filter the lines read from the source file before writing them to the destination file. This approach allows you to process large files efficiently and handle them line by line without consuming excessive memory.

Remember to always close and dispose of the 'StreamReader' and 'StreamWriter' instances correctly to prevent resource leaks and ensure proper management of file streams. The 'using' statement provides a convenient way to handle this automatically.