SoFunction
Updated on 2025-04-13

Detailed explanation of the usage example of StreamReader/StreamWriter in C#

Preface

In C# development,StreamReaderandStreamWriterIt is the core class for processing text files and belongs toNamespace. They operate text data based on Stream, support reading and writing, encoding settings, asynchronous operations, etc., and are suitable for logging, configuration file processing, data export and other scenarios. This article will comprehensively analyze its core functions, performance optimization and common problem solutions from basic to advanced usage, combining code examples.

1. What are StreamReader and StreamWriter?

1. Definition

  • StreamReader: Used in slave streams (such as files, network streams)Read text data, supports line by line reading, reading of specified length data or reading all content at once.
  • StreamWriter: used to flowWrite text data, supports append mode, formatted output and custom encoding.

StreamReaderandStreamWriteryesTwo classes in the namespace, which are used to read and write text data respectively. Both inherit fromTextReaderandTextWriterAbstract classes, usually withFileStreamMemoryStreamIsostream use.

2. Features

  • Provides convenient methods to read and write text data, supporting multiple encoding formats.
  • It can process large files, gradually read or write data through streaming, saving memory.
  • Supports asynchronous operations to improve program responsiveness and performance.

3. Purpose

  • Read and write text files
    • AlternativeFileStreamThe complexity of direct manipulation of bytes, automatically handling encoding and line breaks. Such as log files, configuration files, etc.
  • Network flow analysis
    • andNetworkStreamCombined, it realizes efficient decoding of HTTP response content.
  • Memory flow operation
    • CooperateMemoryStreamHandles in-memory text caches, such as JSON/XML serialization.
  • Logs and data records: Supports append mode writing to avoid frequent overwriting of file content.

Applicable to the following scenarios:

  • Logging: Append the log to the file.
  • Configuration file operation: Read.ini.jsonetc.
  • Data Export: Write data to CSV and TXT files.

4. Why do you need StreamReader/StreamWriter?

When processing text files in C#, use them directlyFileStreamOperating byte arrays is not only cumbersome, but also requires manual handling of encoding, line breaks and other issues.StreamReaderandStreamWriterIt provides a more advanced text stream operation interface, supports automatic encoding detection, line break processing and convenient reading and writing methods, greatly simplifying the development process.

2. Basic usage

1. Create StreamReader and StreamWriter objects

In C#, there are many ways to createStreamReaderandStreamWriterObject:

1) Create from file path

Create using file pathStreamReaderandStreamWriterObjects are the most common method.
Automatically process encoding (default UTF-8)

using ;
// Create StreamReaderusing (StreamReader reader = new StreamReader(""))
{
    // Read operation}
// Create StreamWriterusing (StreamWriter writer = new StreamWriter(""))
{
    // Write operation}

2) Create from stream

It can also be from existing streamsStreamObject creationStreamReaderandStreamWriter, for example fromMemoryStreamor network flow,FileStream, suitable for complex scenarios.

using ;
// Create from MemoryStreamMemoryStream memoryStream = new MemoryStream();
StreamReader reader = new StreamReader(memoryStream);
StreamWriter writer = new StreamWriter(memoryStream);
// Create from FileStreamFileStream fs = new FileStream("", );
using (StreamReader sr = new StreamReader(fs)) { /*...*/ }

3) Coding and format settings

▶ Specify the encoding

The default encoding isUTF-8, but other encodings can be specified through the constructor (e.g.UTF-16ASCII):

// Use UTF-16 to encodeusing (StreamWriter writer = new StreamWriter("", false, ))
{
    ("Hello, Unicode!");
}

▶ Append write mode

By specifyingStreamWriterofappendThe parameters aretrueSet to Append write(append: true)。

StreamWriter sw = new StreamWriter("", true, Encoding.UTF8); // Added mode

▶ Controls whether the underlying stream is closed

leaveOpen: Controls whether the underlying stream is turned off with the reader and writer (defaultfalse)。

MemoryStream  ms= new MemoryStream();
StreamReader streamReader = new StreamReader(ms, , leaveOpen: true);

▶ Automatically detect coding

passStreamReaderofDetectEncodingFromByteOrderMarksAttributes, automatically identify BOM tags:

using (StreamReader reader = new StreamReader("", Encoding.UTF8, detectEncodingFromByteOrderMarks:true))
{
    // If there is a BOM at the beginning of the file, the encoding will be automatically detected    string content = ();
}

2. Write data using StreamWriter

StreamWriterProvides a variety of methods to write text data, the most commonly used ones areWriteandWriteLinemethod.

1) Write data

useWriteMethods can write data to files. Supports strings, numerical values ​​and other types.

using (StreamWriter writer = new StreamWriter(""))
{
	// Write different types of data	(1.1f);
	(42);
	(new byte[] { 1, 2, 3 });
    ("Hello, World!");
}

2) Write data with newline characters

useWriteLineMethods can write data with newlines. Supports strings, numerical values ​​and other types.

using (StreamWriter writer = new StreamWriter(""))
{
	// Write different types of data	(1.1f);
	(42);
	(new byte[] { 1, 2, 3 });
    ("Hello, World!");
}

3. Use StreamReader to read data

StreamReaderProvides a variety of methods to read text data, the most commonly used one isReadReadLineandReadToEndmethod.

1) Read characters

useReadMethods can read a character.

using (StreamReader reader = new StreamReader(""))
{
    int character;
    while ((character = ()) != -1)
    {
        ((char)character);
    }
}

2) Read a line

useReadLineMethods can read a line of text.

using (StreamReader reader = new StreamReader(""))
{
    string line;
    while ((line = ()) != null)
    {
        (line);
    }
}

3) Read all text

useReadToEndMethods can read the contents of the entire file.

using (StreamReader reader = new StreamReader(""))
{
    string content = ();
    (content);
}

Batch operationReadToEnd()Read the full text at one time.Write()Supports character array writing.

4. Common properties and methods of StreamReader and StreamWriter

1) Common properties and methods of StreamReader

  • BaseStream: GetStreamReaderThe basic stream used.
  • CurrentEncoding: Get the currently used character encoding.
  • EndOfStream: Indicates whether the end of the stream has been reached.
  • Peek: View the next character without reading it.
  • Read: Read a single character or character array.
  • ReadBlock: Read a specified number of characters.
  • ReadLine: Read a line of text.
  • ReadToEnd: Read all text in the stream.

2) Common properties and methods of StreamWriter

  • BaseStream: GetStreamWriterThe basic stream used.
  • AutoFlush: Gets or sets a value indicating whether the stream is automatically refreshed after data is written.
  • Encoding: Get the currently used character encoding.
  • Write: Write the specified data.
  • WriteLine: Write the specified data and add a newline character.
  • Flush: Write all buffered characters to the underlying stream.
  • Close: Close the flow and free all related resources.

3) Use examples

▶ Get the current code

AvailableCurrentEncodingAttributes get the currently used encoding.

using (StreamReader reader = new StreamReader(""))
{
    Encoding encoding = ;
    ("Encoding: " + );
}

▶ Get the basic stream object

useBaseStreamProperties can obtain the underlying stream object.

using (StreamReader reader = new StreamReader(""))
{
    Stream stream = ;
    // Operation flow}

▶ Indicates whether the end of the stream has been reached

  while (!) 
  {
      string line = ();
      (line);
  }

5. Sample code

Here is a complete example that demonstrates how to use itStreamReaderandStreamWriter

class Program
{
    static void Main()
    {
        string filePath = "";
        // Write data using StreamWriter        using (StreamWriter writer = new StreamWriter(filePath))
        {
            ("Hello, World!");
            ("This is a new line.");
            ("The answer is: 42");
        }
        // Use StreamReader to read data        using (StreamReader reader = new StreamReader(filePath))
        {
            string line;
            while ((line = ()) != null)
            {
                (line);
            }
        }
        // Use StreamReader to read data + EndOfStream attribute judgment        using (StreamReader reader = new StreamReader(filePath))
        {
            while (!)
            {
                (());
            }
        }
        // Read the entire file content        using (StreamReader reader = new StreamReader(filePath))
        {
            (());
        }
        string content = (filePath);
        ("File content:");
        (content);
        // Read characters        using (StreamReader reader = new StreamReader(filePath))
        {
            int character;
            while ((character = ()) != -1)
            {
                ((char)character);
            }
        }
    }
}

Through this example, we can seeStreamReaderandStreamWriterHow convenient and efficient it is to process text files. They provide rich features to meet a variety of text processing needs.

3. Advanced usage

1. Advanced Tips

1) Asynchronous operation

useReadAsyncWriteAsyncImplement asynchronous reading and writing, avoid blocking the main thread, and improve I/O performance

public async Task WriteAsync()
{
    using (StreamWriter writer = new StreamWriter(""))
    {
        await ("Async write");
    }
}
public async Task ReadAsync()
{
    using (StreamReader reader = new StreamReader(""))
    {
        string content = await ();
    }
}

2) Buffer optimization

Pre-allocated capacity: If the file size is known, specify it during initializationbufferSizeReduce capacity expansion overhead. Balancing performance and memory usage

// Create streams with custom buffersusing (StreamReader reader = new StreamReader("", Encoding.UTF8, true, 8192))
{
    // Buffer size is 8KB}

3) Large file processing

Read large files line by line to avoid memory overflow:

using (StreamReader reader = new StreamReader("large_file.txt"))
{
    string line;
    while ((line = await ()) != null)
    {
        // Process each line    }
}

4) Explicitly refresh the buffer

  • Explicitly refresh the buffer: Called during high-frequency writingFlush()Avoid memory accumulation.
  • Delayed writes and batch commits
 = false;  // Turn off automatic refreshfor (int i = 0; i < 1000; i++) {
    ($"Data {i}");
}
();  // Manual batch submission

2. Advanced application examples

1) Case 1: CSV file analysis

Assume that you need to read a comma-separated CSV file and extract the data:

using (StreamReader sr = new StreamReader("")) 
{
    while (!) 
    {
        string line = ();
        string[] fields = (',').Select(f => ()).ToArray();
        // Process field data...    }
}

Advantages: Automatically handle encoding and line breaks, simplifying string segmentation logic.

2) Case 2: Line-by-line processing of large files and memory optimization

When processing GB-level log files, it is necessary to avoid loading all data at once and causing memory overflow:

using (var sr = new StreamReader("", Encoding.UTF8, bufferSize: 8192)) 
{
    while (!) 
    {
        string line = ();
        if (("ERROR")) 
        {
            // Handle error lines in real time        }
    }
}

Optimization points:

  • set upbufferSize8KB (default 1KB), reducing the number of disk reads.
  • Free memory line by line to avoidReadToEnd()full load risk.

3) Case 3: Logging system

public static void Log(string message)
{
    using var writer = new StreamWriter("", true);
    ($"[{:yyyy-MM-dd HH:mm:ss}] {message}");
}

4) Case 4: Configuration file reading and writing

var config = new Dictionary<string, string>();
using var reader = new StreamReader("");
while ((line = ()) != null)
{
    var parts = ('=');
    if ( == 2)
    {
        config[parts[0]] = parts[1];
    }
}

4. Frequently Asked Questions and Best Practices

1. FAQ

1) Exception when the file does not exist

try
{
    using (StreamReader reader = new StreamReader("non_existent.txt"))
    {
        // Process files    }
}
catch (FileNotFoundException ex)
{
    ("The file does not exist:" + );
}

2) The encoding mismatch leads to garbled code

Ensure that the encoding is consistent during reading and writing:

//Use UTF-8 when writingusing (StreamWriter writer = new StreamWriter("", false, Encoding.UTF8)) { ... }
// Specify the same encoding when readingusing (StreamReader reader = new StreamReader("", Encoding.UTF8)) { ... }

3) Resources not released

Always useusingStatement ensures that the stream is closed correctly:

// Error example: using not usedStreamReader reader = new StreamReader("");
// ... Not closed after processing, which may cause the file to be locked(); // Need to call manually// Correct way: use using automatically release resourcesusing (StreamReader reader = new StreamReader("")) { ... }
// C#8+Simplified writingusing var writer = new StreamWriter("");

4) Coding issues

If the file contains BOM (byte order mark), it can be passeddetectEncodingFromByteOrderMarks: trueAutomatic recognition.
When processing multi-coded files with BOM headers, automatically adapt the encoding:

using (FileStream fs = ("mixed_encoding.txt")) 
{
    using (StreamReader sr = new StreamReader(fs, , detectEncodingFromByteOrderMarks: true)) 
    {
        ($"Encoding detected:{}");
        //Analyze the content according to the correct encoding    }
}

Tips: ByCurrentEncodingAttributes get the actual encoding used.

5) Reset the flow position

Need to call after writingSeek(0, )Reset position, otherwise subsequent reads will start at the end.

6) Avoid nested stream lifecycle

Avoid nested stream lifecycle: Ensure that the underlying stream and reader release order are consistent (turn off the reader and write first, then turn off the stream).

2. Summary of best practices

  • Resource Management: Used statement must be used
  • Clear code: Try to specify the code to determine the code
  • Exception handling: Fully capture of IO exceptions
  • Performance considerations: Large files are read using buffer
  • Mode selection: Pay attention to parameter settings for additional mode

This is the end of this article about the detailed explanation of the use examples of StreamReader/StreamWriter in C#. For more related contents of C# StreamReader/StreamWriter, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!