Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Handling Data I/O in C# Using Streams

Tech May 15 1

In C#, input and output operations are primarily handled through the System.IO namespace. The central concept is the Stream, an abstract class that provides a generic view of a sequence of bytes. Streams involve three fundamental operations: reading, writing, and seeking.

The System.IO namespace organizes IO functionality into several key classes:

  • Stream: The abstract base class. Key derived classes include:
    • MemoryStream: Operates on data stored in memory.
    • BufferedStream: Adds a buffering layer to read/write operations on another stream to improve performance.
    • FileStream: Designed for file-based operations.
  • BinaryReader/BinaryWriter: Helper classes for reading and writing primitive data types as binary values.
  • TextReader/TextWriter: Abstract base classes for handling character-based I/O. Their derived classes include StreamReader/StreamWriter (for files) and StringReader/StringWriter (for strings).

Memory and Buffered Streams

The following example demonstrates how to use a MemoryStream backed by a BufferedStream. Data is written to the buffer and then read back.

using System;
using System.IO;

public class MemoryBufferExample
{
    public void Execute()
    {
        // Create a memory stream wrapped in a buffered stream
        using (var memoryStream = new MemoryStream())
        using (var bufferedStream = new BufferedStream(memoryStream))
        {
            // Write bytes 0 through 9
            for (int i = 0; i < 10; i++)
            {
                bufferedStream.WriteByte((byte)i);
            }

            // Reset the position to the beginning to read data
            bufferedStream.Position = 0;

            // Read data into a byte array
            byte[] buffer = new byte[10];
            bufferedStream.Read(buffer, 0, buffer.Length);

            foreach (byte b in buffer)
            {
                Console.WriteLine($"Value read: {b}");
            }

            // Read a single byte manually (will be the last one read or -1 if end of stream)
            int nextByte = bufferedStream.ReadByte();
            Console.WriteLine($"Final byte read attempt: {nextByte}");
        }
    }
}

File Streams with Binary Readers and Writers

For binary data, FileStream is often paired with BinaryWriter and BinaryReader. It is crucial to read data using the correct data type; for instance, an int written via BinaryWriter occupies 4 bytes and must be read using ReadInt32, not ReadByte.

using System;
using System.IO;

public class FileBinaryExample
{
    public void ProcessFile(string path)
    {
        // Write binary data to a file
        using (var fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
        using (var writer = new BinaryWriter(fileStream))
        {
            for (int i = 1; i <= 10; i++)
            {
                writer.Write(i); // Writes a 4-byte integer
            }
        }

        // Read binary data from the file
        using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
        using (var reader = new BinaryReader(fileStream))
        {
            // Ensure the stream is read to the end
            while (fileStream.Position < fileStream.Length)
            {
                // Must use ReadInt32 to match the written data type
                int value = reader.ReadInt32();
                Console.WriteLine($"Integer read: {value}");
            }
        }
    }
}

Text Streams

When dealing with text files, StreamWriter and StreamReader simplify the process of writing and reading strings. These classes handle character encoding automatically.

using System;
using System.IO;

public class TextFileExample
{
    public void ManageTextFile(string filePath)
    {
        // Write text to the file
        // The 'true' argument appends data; 'false' overwrites the file
        using (var writer = new StreamWriter(filePath, false))
        {
            for (int i = 1; i < 5; i++)
            {
                writer.WriteLine($"Line number: {i}");
            }
        }

        // Read text from the file
        using (var reader = new StreamReader(filePath))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }
        }
    }
}

String Streams

StringWriter and StringReader allow you to treat strings as streams. This is useful for manipulating string data in memory using the stream interface. StringWriter typically wraps a StringBuilder.

using System;
using System.IO;
using System.Text;

public class StringStreamExample
{
    public void ProcessStringData()
    {
        var stringBuilder = new StringBuilder();
        
        // Write to the StringBuilder via StringWriter
        using (var stringWriter = new StringWriter(stringBuilder))
        {
            for (int i = 0; i < 5; i++)
            {
                stringWriter.WriteLine($"Input entry {i}");
            }
        }

        string content = stringBuilder.ToString();
        Console.WriteLine("Full Content:");
        Console.WriteLine(content);

        // Read from the string via StringReader
        using (var stringReader = new StringReader(content))
        {
            string line = stringReader.ReadLine();
            Console.WriteLine($"First line read: {line}");
        }
    }
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.