欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#中的 StreamReader/StreamWriter 使用示例詳解

 更新時(shí)間:2025年03月27日 11:10:06   作者:鯉籽鯤  
在 C# 開(kāi)發(fā)中,StreamReader 和 StreamWriter 是處理文本文件的核心類(lèi),屬于 System.IO 命名空間,本文將從基礎(chǔ)到高級(jí)用法,結(jié)合代碼示例,全面解析其核心功能、性能優(yōu)化及常見(jiàn)問(wèn)題解決方案,感興趣的朋友一起看看吧

前言

在 C# 開(kāi)發(fā)中,StreamReaderStreamWriter 是處理文本文件的核心類(lèi),屬于 System.IO 命名空間。它們基于流(Stream)操作文本數(shù)據(jù),支持讀寫(xiě)、編碼設(shè)置、異步操作等,適用于日志記錄、配置文件處理、數(shù)據(jù)導(dǎo)出等場(chǎng)景。本文將從基礎(chǔ)到高級(jí)用法,結(jié)合代碼示例,全面解析其核心功能、性能優(yōu)化及常見(jiàn)問(wèn)題解決方案。

一、什么是 StreamReader 和 StreamWriter?

1. 定義

  • StreamReader:用于從流(如文件、網(wǎng)絡(luò)流)中讀取文本數(shù)據(jù),支持逐行讀取、讀取指定長(zhǎng)度數(shù)據(jù)或一次性讀取全部?jī)?nèi)容。
  • StreamWriter:用于向流中寫(xiě)入文本數(shù)據(jù),支持追加模式、格式化輸出及自定義編碼。

StreamReaderStreamWriterSystem.IO 命名空間中的兩個(gè)類(lèi),它們分別用于讀取和寫(xiě)入文本數(shù)據(jù)。兩者均繼承自 TextReaderTextWriter 抽象類(lèi),通常與 FileStream、MemoryStream 等流結(jié)合使用。

2. 特點(diǎn)

  • 提供了方便的方法來(lái)讀取和寫(xiě)入文本數(shù)據(jù),支持多種編碼格式。
  • 可以處理大文件,通過(guò)流的方式逐步讀取或?qū)懭霐?shù)據(jù),節(jié)省內(nèi)存。
  • 支持異步操作,提高程序的響應(yīng)性和性能。

3. 用途

  • 文本文件讀寫(xiě)
    • 替代 FileStream 直接操作字節(jié)的復(fù)雜性,自動(dòng)處理編碼和換行符。如日志文件、配置文件等。
  • 網(wǎng)絡(luò)流解析
    • NetworkStream 結(jié)合,實(shí)現(xiàn) HTTP 響應(yīng)內(nèi)容的高效解碼。
  • 內(nèi)存流操作
    • 配合 MemoryStream 處理內(nèi)存中的文本緩存,如 JSON/XML 序列化。
  • 日志與數(shù)據(jù)記錄: 支持追加模式寫(xiě)入,避免頻繁覆蓋文件內(nèi)容。

適用于以下場(chǎng)景:

  • 日志記錄:將日志追加到文件。
  • 配置文件操作:讀取 .ini、.json 等文本配置。
  • 數(shù)據(jù)導(dǎo)出:將數(shù)據(jù)寫(xiě)入 CSV、TXT 文件。

4. 為什么需要 StreamReader/StreamWriter?

在C#中處理文本文件時(shí),直接使用 FileStream 操作字節(jié)數(shù)組不僅繁瑣,還需手動(dòng)處理編碼、換行符等問(wèn)題。StreamReaderStreamWriter 提供了更高級(jí)的文本流操作接口,支持自動(dòng)編碼檢測(cè)、換行符處理及便捷的讀寫(xiě)方法,大幅簡(jiǎn)化開(kāi)發(fā)流程。

二、基礎(chǔ)用法

1. 創(chuàng)建 StreamReader 和 StreamWriter 對(duì)象

在 C# 中,有多種方式可以創(chuàng)建 StreamReaderStreamWriter 對(duì)象:

1)從文件路徑創(chuàng)建

使用文件路徑創(chuàng)建 StreamReaderStreamWriter 對(duì)象是最常見(jiàn)的方法。
自動(dòng)處理編碼(默認(rèn)UTF-8)

using System.IO;
// 創(chuàng)建 StreamReader
using (StreamReader reader = new StreamReader("example.txt"))
{
    // 讀取操作
}
// 創(chuàng)建 StreamWriter
using (StreamWriter writer = new StreamWriter("example.txt"))
{
    // 寫(xiě)入操作
}

2)從流創(chuàng)建

也可以從現(xiàn)有的流 Stream對(duì)象創(chuàng)建 StreamReaderStreamWriter,例如從 MemoryStream 或網(wǎng)絡(luò)流、 FileStream,適合復(fù)雜場(chǎng)景。

using System.IO;
// 從 MemoryStream 創(chuàng)建
MemoryStream memoryStream = new MemoryStream();
StreamReader reader = new StreamReader(memoryStream);
StreamWriter writer = new StreamWriter(memoryStream);
// 從 FileStream 創(chuàng)建
FileStream fs = new FileStream("data.bin", FileMode.Open);
using (StreamReader sr = new StreamReader(fs)) { /*...*/ }

3)編碼與格式設(shè)置

? 指定編碼

默認(rèn)編碼為 UTF-8,但可通過(guò)構(gòu)造函數(shù)指定其他編碼(如 UTF-16、ASCII):

// 使用 UTF-16 編碼
using (StreamWriter writer = new StreamWriter("data.txt", false, Encoding.Unicode))
{
    writer.WriteLine("Hello, Unicode!");
}

? 追加寫(xiě)入模式

通過(guò)指定StreamWriterappend參數(shù)為true 設(shè)置為 追加寫(xiě)入(append: true)。

StreamWriter sw = new StreamWriter("log.txt", true, Encoding.UTF8); // 追加模式

? 控制底層流是否關(guān)閉

leaveOpen:控制底層流是否隨讀寫(xiě)器關(guān)閉(默認(rèn) false)。

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

? 自動(dòng)檢測(cè)編碼

通過(guò) StreamReaderDetectEncodingFromByteOrderMarks 屬性,自動(dòng)識(shí)別 BOM 標(biāo)記:

using (StreamReader reader = new StreamReader("data.txt", Encoding.UTF8, detectEncodingFromByteOrderMarks:true))
{
    // 如果文件開(kāi)頭有 BOM,會(huì)自動(dòng)檢測(cè)編碼
    string content = reader.ReadToEnd();
}

2. 使用 StreamWriter 寫(xiě)入數(shù)據(jù)

StreamWriter 提供了多種方法來(lái)寫(xiě)入文本數(shù)據(jù),最常用的是 WriteWriteLine 方法。

1)寫(xiě)入數(shù)據(jù)

使用 Write 方法可以寫(xiě)入數(shù)據(jù)到文件中。支持字符串、數(shù)值等類(lèi)型。

using (StreamWriter writer = new StreamWriter("example.txt"))
{
	// 寫(xiě)入不同類(lèi)型的數(shù)據(jù)
	writer.Write(1.1f);
	writer.Write(42);
	writer.Write(new byte[] { 1, 2, 3 });
    writer.Write("Hello, World!");
}

2)寫(xiě)入帶換行符的數(shù)據(jù)

使用 WriteLine 方法可以寫(xiě)入一個(gè)帶換行符的數(shù)據(jù)。支持字符串、數(shù)值等類(lèi)型。

using (StreamWriter writer = new StreamWriter("example.txt"))
{
	// 寫(xiě)入不同類(lèi)型的數(shù)據(jù)
	writer.WriteLine(1.1f);
	writer.WriteLine(42);
	writer.WriteLine(new byte[] { 1, 2, 3 });
    writer.WriteLine("Hello, World!");
}

3. 使用 StreamReader 讀取數(shù)據(jù)

StreamReader 提供了多種方法來(lái)讀取文本數(shù)據(jù),最常用的是 ReadReadLineReadToEnd 方法。

1)讀取字符

使用 Read 方法可以讀取一個(gè)字符。

using (StreamReader reader = new StreamReader("example.txt"))
{
    int character;
    while ((character = reader.Read()) != -1)
    {
        Console.Write((char)character);
    }
}

2)讀取一行

使用 ReadLine 方法可以讀取一行文本。

using (StreamReader reader = new StreamReader("example.txt"))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine(line);
    }
}

3)讀取所有文本

使用 ReadToEnd 方法可以讀取整個(gè)文件的內(nèi)容。

using (StreamReader reader = new StreamReader("example.txt"))
{
    string content = reader.ReadToEnd();
    Console.WriteLine(content);
}

批量操作ReadToEnd() 一次性讀取全文,Write() 支持字符數(shù)組寫(xiě)入。

4. StreamReader 和 StreamWriter 的常用屬性和方法

1)StreamReader的常用屬性和方法

  • BaseStream:獲取StreamReader所使用的基礎(chǔ)流。
  • CurrentEncoding:獲取當(dāng)前使用的字符編碼。
  • EndOfStream:指示是否已到達(dá)流的末尾。
  • Peek:查看下一個(gè)字符而不讀取它。
  • Read:讀取單個(gè)字符或字符數(shù)組。
  • ReadBlock:讀取指定數(shù)量的字符。
  • ReadLine:讀取一行文本。
  • ReadToEnd:讀取流中的所有文本。

2)StreamWriter的常用屬性和方法

  • BaseStream:獲取StreamWriter所使用的基礎(chǔ)流。
  • AutoFlush:獲取或設(shè)置一個(gè)值,該值指示是否在寫(xiě)入數(shù)據(jù)后自動(dòng)刷新流。
  • Encoding:獲取當(dāng)前使用的字符編碼。
  • Write:寫(xiě)入指定的數(shù)據(jù)。
  • WriteLine:寫(xiě)入指定的數(shù)據(jù),并添加換行符。
  • Flush:將所有緩沖的字符寫(xiě)入基礎(chǔ)流。
  • Close:關(guān)閉流并釋放所有相關(guān)資源。

3)使用示例

? 獲取當(dāng)前編碼

可以使用 CurrentEncoding 屬性獲取當(dāng)前使用的編碼。

using (StreamReader reader = new StreamReader("example.txt"))
{
    Encoding encoding = reader.CurrentEncoding;
    Console.WriteLine("Encoding: " + encoding.EncodingName);
}

? 獲取基礎(chǔ)流對(duì)象

使用 BaseStream 屬性可以獲取基礎(chǔ)流對(duì)象。

using (StreamReader reader = new StreamReader("example.txt"))
{
    Stream stream = reader.BaseStream;
    // 操作流
}

? 指示是否已到達(dá)流的末尾

  while (!sr.EndOfStream) 
  {
      string line = sr.ReadLine();
      Console.WriteLine(line);
  }

5. 示例代碼

下面是一個(gè)完整的示例,演示了如何使用 StreamReaderStreamWriter

class Program
{
    static void Main()
    {
        string filePath = "example.txt";
        // 使用 StreamWriter 寫(xiě)入數(shù)據(jù)
        using (StreamWriter writer = new StreamWriter(filePath))
        {
            writer.WriteLine("Hello, World!");
            writer.WriteLine("This is a new line.");
            writer.WriteLine("The answer is: 42");
        }
        // 使用 StreamReader 讀取數(shù)據(jù)
        using (StreamReader reader = new StreamReader(filePath))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }
        }
        // 使用 StreamReader 讀取數(shù)據(jù) + EndOfStream 屬性判斷
        using (StreamReader reader = new StreamReader(filePath))
        {
            while (!reader.EndOfStream)
            {
                Console.WriteLine(reader.ReadLine());
            }
        }
        // 讀取整個(gè)文件內(nèi)容
        using (StreamReader reader = new StreamReader(filePath))
        {
            Console.WriteLine(reader.ReadToEnd());
        }
        string content = File.ReadAllText(filePath);
        Console.WriteLine("File content:");
        Console.WriteLine(content);
        // 讀取字符
        using (StreamReader reader = new StreamReader(filePath))
        {
            int character;
            while ((character = reader.Read()) != -1)
            {
                Console.Write((char)character);
            }
        }
    }
}

通過(guò)這個(gè)示例,我們可以看到 StreamReaderStreamWriter 在處理文本文件時(shí)是多么方便和高效。它們提供了豐富的功能,滿(mǎn)足了多種文本處理需求。

三、高級(jí)用法

1. 高級(jí)技巧

1)異步操作

使用 ReadAsync、WriteAsync 實(shí)現(xiàn)異步讀寫(xiě),避免阻塞主線(xiàn)程,提升I/O性能

public async Task WriteAsync()
{
    using (StreamWriter writer = new StreamWriter("data.txt"))
    {
        await writer.WriteLineAsync("異步寫(xiě)入");
    }
}
public async Task ReadAsync()
{
    using (StreamReader reader = new StreamReader("data.txt"))
    {
        string content = await reader.ReadToEndAsync();
    }
}

2)緩沖區(qū)優(yōu)化

預(yù)分配容量:若已知文件大小,初始化時(shí)指定 bufferSize 減少擴(kuò)容開(kāi)銷(xiāo)。 平衡性能與內(nèi)存占用

// 創(chuàng)建帶自定義緩沖區(qū)的流
using (StreamReader reader = new StreamReader("data.txt", Encoding.UTF8, true, 8192))
{
    // 緩沖區(qū)大小為 8KB
}

3)大文件處理

逐行讀取大文件以避免內(nèi)存溢出:

using (StreamReader reader = new StreamReader("large_file.txt"))
{
    string line;
    while ((line = await reader.ReadLineAsync()) != null)
    {
        // 處理每一行
    }
}

4)顯式刷新緩沖區(qū)

  • 顯式刷新緩沖區(qū):高頻寫(xiě)入時(shí)調(diào)用 Flush() 避免內(nèi)存堆積。
  • 延遲寫(xiě)入與批量提交
sw.AutoFlush = false;  // 關(guān)閉自動(dòng)刷新
for (int i = 0; i < 1000; i++) {
    sw.Write($"Data {i}");
}
sw.Flush();  // 手動(dòng)批量提交

2. 高級(jí)應(yīng)用示例

1)案例1:CSV文件解析

假設(shè)需讀取包含逗號(hào)分隔的CSV文件并提取數(shù)據(jù):

using (StreamReader sr = new StreamReader("data.csv")) 
{
    while (!sr.EndOfStream) 
    {
        string line = sr.ReadLine();
        string[] fields = line.Split(',').Select(f => f.Trim()).ToArray();
        // 處理字段數(shù)據(jù)...
    }
}

優(yōu)勢(shì):自動(dòng)處理編碼與換行符,簡(jiǎn)化字符串分割邏輯。

2)案例2:大文件逐行處理與內(nèi)存優(yōu)化

當(dāng)處理 GB 級(jí)日志文件時(shí),需避免一次性加載全部數(shù)據(jù)導(dǎo)致內(nèi)存溢出:

using (var sr = new StreamReader("large.log", Encoding.UTF8, bufferSize: 8192)) 
{
    while (!sr.EndOfStream) 
    {
        string line = sr.ReadLine();
        if (line.Contains("ERROR")) 
        {
            // 實(shí)時(shí)處理錯(cuò)誤行
        }
    }
}

優(yōu)化點(diǎn):

  • 設(shè)置 bufferSize 為 8KB(默認(rèn) 1KB),減少磁盤(pán)讀取次數(shù)。
  • 逐行釋放內(nèi)存,避免 ReadToEnd() 的全量加載風(fēng)險(xiǎn)。

3)案例3:日志記錄系統(tǒng)

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

4)案例4:配置文件讀寫(xiě)

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

四、常見(jiàn)問(wèn)題與最佳實(shí)踐

1. 常見(jiàn)問(wèn)題

1)文件不存在時(shí)的異常

try
{
    using (StreamReader reader = new StreamReader("non_existent.txt"))
    {
        // 處理文件
    }
}
catch (FileNotFoundException ex)
{
    Console.WriteLine("文件不存在:" + ex.Message);
}

2)編碼不匹配導(dǎo)致亂碼

確保讀寫(xiě)時(shí)編碼一致:

// 寫(xiě)入時(shí)使用 UTF-8
using (StreamWriter writer = new StreamWriter("data.txt", false, Encoding.UTF8)) { ... }
// 讀取時(shí)指定相同編碼
using (StreamReader reader = new StreamReader("data.txt", Encoding.UTF8)) { ... }

3)資源未釋放

始終使用 using 語(yǔ)句確保流正確關(guān)閉:

// 錯(cuò)誤示例:未使用 using
StreamReader reader = new StreamReader("data.txt");
// ... 處理后未關(guān)閉,可能導(dǎo)致文件被鎖定
reader.Close(); // 需手動(dòng)調(diào)用
// 正確做法:使用 using 自動(dòng)釋放資源
using (StreamReader reader = new StreamReader("data.txt")) { ... }
// C# 8+簡(jiǎn)化寫(xiě)法
using var writer = new StreamWriter("output.txt");

4)編碼問(wèn)題

若文件包含BOM(字節(jié)順序標(biāo)記),可通過(guò) detectEncodingFromByteOrderMarks: true 自動(dòng)識(shí)別。
處理含 BOM 頭的多編碼文件時(shí),自動(dòng)適配編碼:

using (FileStream fs = File.OpenRead("mixed_encoding.txt")) 
{
    using (StreamReader sr = new StreamReader(fs, Encoding.Default, detectEncodingFromByteOrderMarks: true)) 
    {
        Console.WriteLine($"檢測(cè)到編碼:{sr.CurrentEncoding}");
        // 按正確編碼解析內(nèi)容
    }
}

技巧:通過(guò) CurrentEncoding 屬性獲取實(shí)際使用的編碼。

5)流位置重置

寫(xiě)入后需調(diào)用 Seek(0, SeekOrigin.Begin) 重置位置,否則后續(xù)讀取會(huì)從末尾開(kāi)始。

6)避免嵌套流生命周期

避免嵌套流生命周期:確保底層流與讀寫(xiě)器釋放順序一致(先關(guān)讀寫(xiě)器,再關(guān)流)。

2. 最佳實(shí)踐總結(jié)

  • 資源管理:必須使用using語(yǔ)句
  • 編碼明確:盡量指定確定編碼
  • 異常處理:全面捕獲IO異常
  • 性能考量:大文件使用緩沖讀取
  • 模式選擇:追加模式注意參數(shù)設(shè)置

到此這篇關(guān)于C#中的 StreamReader/StreamWriter 使用示例詳解的文章就介紹到這了,更多相關(guān)C# StreamReader/StreamWriter 使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#中struct與class的區(qū)別詳解

    C#中struct與class的區(qū)別詳解

    本文主要介紹了C#中struct與class的區(qū)別詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • C#使用dynamic類(lèi)型訪問(wèn)JObject對(duì)象

    C#使用dynamic類(lèi)型訪問(wèn)JObject對(duì)象

    這篇文章主要為大家詳細(xì)介紹了C#使用dynamic類(lèi)型訪問(wèn)JObject對(duì)象,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • C#圖像處理之浮雕效果實(shí)現(xiàn)方法

    C#圖像處理之浮雕效果實(shí)現(xiàn)方法

    這篇文章主要介紹了C#圖像處理之浮雕效果實(shí)現(xiàn)方法,可實(shí)現(xiàn)圖片轉(zhuǎn)換成浮雕效果的功能,需要的朋友可以參考下
    2015-04-04
  • 解析C#彩色圖像灰度化算法的實(shí)現(xiàn)代碼詳解

    解析C#彩色圖像灰度化算法的實(shí)現(xiàn)代碼詳解

    本篇文章是對(duì)C#中彩色圖像灰度化算法的實(shí)現(xiàn)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C#使用iTextSharp獲取PDF文件書(shū)簽信息的操作方法

    C#使用iTextSharp獲取PDF文件書(shū)簽信息的操作方法

    C# iTextSharp是一個(gè)用于處理PDF文件的源庫(kù),它提供了一系列的功能,包括創(chuàng)建PDF文件,以及提取和操作PDF文件中的內(nèi)容,本文給大家介紹了C#使用iTextSharp獲取PDF文件書(shū)簽信息的操作方法,需要的朋友可以參考下
    2024-04-04
  • C#中分部類(lèi)和分部方法的應(yīng)用

    C#中分部類(lèi)和分部方法的應(yīng)用

    本篇文章介紹了,C#中分部類(lèi)和分部方法的應(yīng)用。需要的朋友參考下
    2013-04-04
  • C#數(shù)據(jù)類(lèi)型實(shí)現(xiàn)背包、隊(duì)列和棧

    C#數(shù)據(jù)類(lèi)型實(shí)現(xiàn)背包、隊(duì)列和棧

    本文詳細(xì)講解了C#數(shù)據(jù)結(jié)構(gòu)類(lèi)型,并實(shí)現(xiàn)背包、隊(duì)列和棧的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#并行編程之Task同步機(jī)制

    C#并行編程之Task同步機(jī)制

    這篇文章介紹了C#并行編程之Task同步機(jī)制,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • 如何用C#創(chuàng)建用戶(hù)自定義異常淺析

    如何用C#創(chuàng)建用戶(hù)自定義異常淺析

    雖然在 C# 語(yǔ)言中已經(jīng)提供了很多異常處理類(lèi),但在實(shí)際編程中還是會(huì)遇到未涉及的一些異常處理,這篇文章主要給大家介紹了關(guān)于如何用C#創(chuàng)建用戶(hù)自定義異常的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • C#實(shí)現(xiàn)二維數(shù)據(jù)數(shù)組導(dǎo)出到Excel的詳細(xì)過(guò)程

    C#實(shí)現(xiàn)二維數(shù)據(jù)數(shù)組導(dǎo)出到Excel的詳細(xì)過(guò)程

    將數(shù)據(jù)庫(kù)查詢(xún)出來(lái)的數(shù)據(jù)導(dǎo)出并生成?Excel?文件,是項(xiàng)目中經(jīng)常使用的一項(xiàng)功能,本文將介紹通過(guò)數(shù)據(jù)集生成二維數(shù)據(jù)數(shù)組并導(dǎo)出到?Excel,文中有詳細(xì)的代碼供大家參考,需要的朋友可以參考下
    2024-09-09

最新評(píng)論