Preface
In C# development,StreamReader
andStreamWriter
It 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.
StreamReader
andStreamWriter
yesTwo classes in the namespace, which are used to read and write text data respectively. Both inherit from
TextReader
andTextWriter
Abstract classes, usually withFileStream
、MemoryStream
Isostream 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:
- Alternative
FileStream
The complexity of direct manipulation of bytes, automatically handling encoding and line breaks. Such as log files, configuration files, etc.
- Alternative
-
Network flow analysis:
- and
NetworkStream
Combined, it realizes efficient decoding of HTTP response content.
- and
-
Memory flow operation:
- Cooperate
MemoryStream
Handles in-memory text caches, such as JSON/XML serialization.
- Cooperate
- 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
、.json
etc. - Data Export: Write data to CSV and TXT files.
4. Why do you need StreamReader/StreamWriter?
When processing text files in C#, use them directlyFileStream
Operating 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 createStreamReader
andStreamWriter
Object:
1) Create from file path
Create using file pathStreamReader
andStreamWriter
Objects 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 streamsStream
Object creationStreamReader
andStreamWriter
, for example fromMemoryStream
or 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-16
、ASCII
):
// Use UTF-16 to encodeusing (StreamWriter writer = new StreamWriter("", false, )) { ("Hello, Unicode!"); }
▶ Append write mode
By specifyingStreamWriter
ofappend
The parameters aretrue
Set 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
passStreamReader
ofDetectEncodingFromByteOrderMarks
Attributes, 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
StreamWriter
Provides a variety of methods to write text data, the most commonly used ones areWrite
andWriteLine
method.
1) Write data
useWrite
Methods 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
useWriteLine
Methods 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
StreamReader
Provides a variety of methods to read text data, the most commonly used one isRead
、ReadLine
andReadToEnd
method.
1) Read characters
useRead
Methods can read a character.
using (StreamReader reader = new StreamReader("")) { int character; while ((character = ()) != -1) { ((char)character); } }
2) Read a line
useReadLine
Methods can read a line of text.
using (StreamReader reader = new StreamReader("")) { string line; while ((line = ()) != null) { (line); } }
3) Read all text
useReadToEnd
Methods can read the contents of the entire file.
using (StreamReader reader = new StreamReader("")) { string content = (); (content); }
Batch operation:
ReadToEnd()
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
: GetStreamReader
The 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
: GetStreamWriter
The 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
AvailableCurrentEncoding
Attributes get the currently used encoding.
using (StreamReader reader = new StreamReader("")) { Encoding encoding = ; ("Encoding: " + ); }
▶ Get the basic stream object
useBaseStream
Properties 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 itStreamReader
andStreamWriter
:
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 seeStreamReader
andStreamWriter
How 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
useReadAsync
、WriteAsync
Implement 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 initializationbufferSize
Reduce 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 writing
Flush()
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 up
bufferSize
8KB (default 1KB), reducing the number of disk reads. - Free memory line by line to avoid
ReadToEnd()
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 useusing
Statement 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: true
Automatic 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: ByCurrentEncoding
Attributes 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!