ZetCode

C# StreamWriter

最后修改于 2025 年 4 月 20 日

本教程解释了如何在 C# 中使用 StreamWriter 类将文本数据写入文件。 StreamWriter 提供了使用各种编码将文本写入流的方法。

StreamWriter 类实现了一个 TextWriter,用于以特定编码将字符写入流。它通常用于写入文本文件。

StreamWriter 自动处理文本编码,并提供高效的缓冲写入。它通常与 StreamReader 配对用于读取文本文件。

基本 StreamWriter 示例

此示例演示了如何使用 StreamWriter 将文本写入文件。 它展示了创建和写入文本文件的最简单方法。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        // Create a file and write text to it
        using (StreamWriter writer = new StreamWriter("example.txt"))
        {
            writer.WriteLine("This is the first line.");
            writer.WriteLine("This is the second line.");
            writer.Write("This is ");
            writer.Write("a single line.");
        }

        Console.WriteLine("Text written to file successfully.");
    }
}

该示例创建一个名为“example.txt”的新文件并写入三行文本。 using 语句确保正确清理资源。 WriteLine 在每个字符串后添加一个换行符,而 Write 不添加。

using 块结束时,文件会自动关闭。 这是使用文件流的推荐方式,因为它会自动处理释放,即使发生异常也是如此。

追加到现有文件

StreamWriter 可以将文本追加到现有文件,而不是覆盖它们。 此示例展示了如何向现有文件添加内容。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        // Append text to an existing file
        using (StreamWriter writer = new StreamWriter("log.txt", true))
        {
            writer.WriteLine($"Log entry: {DateTime.Now}");
            writer.WriteLine("Application started successfully.");
            writer.WriteLine();
        }

        Console.WriteLine("Log entry appended to file.");
    }
}

StreamWriter 构造函数中的第二个参数指定是否追加到文件。 将其设置为 true 可保留现有内容。 这对于希望维护条目历史记录的日志文件特别有用。

每次运行此程序都会将新的日志条目添加到文件中,而不会影响之前的内容。 空的 WriteLine 在条目之间添加一个空行,以提高可读性。

指定文件编码

StreamWriter 允许在写入文件时指定文本编码。 此示例演示了使用 UTF-8 和 UTF-16 编码进行写入。

Program.cs
using System;
using System.IO;
using System.Text;

class Program
{
    static void Main()
    {
        // Write with UTF-8 encoding (default)
        using (StreamWriter writer = new StreamWriter("utf8.txt", false, Encoding.UTF8))
        {
            writer.WriteLine("UTF-8 encoded text: Café");
        }

        // Write with UTF-16 encoding
        using (StreamWriter writer = new StreamWriter("utf16.txt", false, Encoding.Unicode))
        {
            writer.WriteLine("UTF-16 encoded text: Café");
        }

        Console.WriteLine("Files written with different encodings.");
    }
}

StreamWriter 构造函数中的第三个参数指定文本编码。 如果未指定编码,则 UTF-8 是默认值。 不同的编码以不同的方式处理特殊字符和国际文本。

对于 ASCII 字符,UTF-8 更节省空间,而对于具有非拉丁字符的语言,UTF-16 可能更好。 该选择取决于您的具体要求和预期内容。

写入格式化文本

StreamWriter 支持类似于 Console.WriteLine 的格式化写入。 此示例展示了如何将格式化的字符串写入文件。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string product = "Coffee";
        decimal price = 4.99m;
        int quantity = 10;

        using (StreamWriter writer = new StreamWriter("receipt.txt"))
        {
            writer.WriteLine("RECEIPT");
            writer.WriteLine("-------");
            writer.WriteLine("Date: {0:d}", DateTime.Today);
            writer.WriteLine("Product: {0}", product);
            writer.WriteLine("Price: {0:C}", price);
            writer.WriteLine("Quantity: {0}", quantity);
            writer.WriteLine("Total: {0:C}", price * quantity);
        }

        Console.WriteLine("Formatted receipt written to file.");
    }
}

该示例使用带有占位符({0}、{1} 等)的复合格式来创建结构化的收据。 像 :d(日期)和 :C(货币)这样的格式说明符使输出更具可读性。

这种方法对于生成结构化文档、报告或任何需要一致格式的输出都非常有用。 支持 Console.WriteLine 中提供的相同格式化选项。

刷新和 AutoFlush

默认情况下,StreamWriter 缓冲写入。 此示例演示了手动刷新和 AutoFlush 属性。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        // With default buffering
        using (StreamWriter writer = new StreamWriter("buffered.txt"))
        {
            writer.WriteLine("This may not appear immediately.");
            Console.WriteLine("Check file - content may not be there yet.");
            writer.Flush(); // Force write to disk
            Console.WriteLine("Now content should be in file.");
        }

        // With AutoFlush enabled
        using (StreamWriter writer = new StreamWriter("autoflush.txt"))
        {
            writer.AutoFlush = true;
            writer.WriteLine("This appears immediately after each write.");
            Console.WriteLine("Content should be in file already.");
        }
    }
}

Flush 强制将任何缓冲的数据写入文件。 AutoFlush = true 使这在每次写入后自动发生。 缓冲通过减少磁盘 I/O 操作来提高性能。

当您需要确保数据在特定点写入时,手动刷新非常有用。 AutoFlush 很方便,但可能会影响许多小写入的性能。 根据您的需求选择合适的方法。

写入 MemoryStream

StreamWriter 可以写入任何 Stream,包括 MemoryStream。 此示例展示了将文本写入内存而不是文件。

Program.cs
using System;
using System.IO;
using System.Text;

class Program
{
    static void Main()
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (StreamWriter writer = new StreamWriter(memoryStream, Encoding.UTF8, 1024, true))
            {
                writer.WriteLine("This text is written to memory.");
                writer.WriteLine("Current time: {0:T}", DateTime.Now);
            }

            // Read back from the MemoryStream
            memoryStream.Position = 0;
            using (StreamReader reader = new StreamReader(memoryStream))
            {
                string content = reader.ReadToEnd();
                Console.WriteLine("Memory content:");
                Console.WriteLine(content);
            }
        }
    }
}

该示例将文本写入 MemoryStream,然后将其读回。 StreamWriter 构造函数参数控制编码、缓冲区大小和 leave-open 行为。 这种技术对于内存中的文本处理非常有用。

MemoryStream 通常用于单元测试、网络通信,或者当您需要在不创建物理文件的情况下处理文本时。 在读回内容之前,需要进行 Position = 0 重置。

异步写入

StreamWriter 支持异步操作,以在 I/O 密集型应用程序中获得更好的性能。 此示例显示了异步文件写入。

Program.cs
using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        try
        {
            using (StreamWriter writer = new StreamWriter("async.txt"))
            {
                await writer.WriteLineAsync("First line written asynchronously.");
                await writer.WriteAsync("This is ");
                await writer.WriteLineAsync("also async.");
                await writer.FlushAsync();
            }

            Console.WriteLine("Asynchronous write completed.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

异步方法 (WriteLineAsync, WriteAsync, FlushAsync) 在 I/O 操作期间不会阻塞调用线程。 这提高了 GUI 应用程序的响应能力和服务器应用程序的可扩展性。

async/await 模式使异步代码几乎与同步代码一样简单。 在执行文件 I/O 操作时,始终处理潜在的异常。

来源

StreamWriter 类文档

本教程介绍了如何使用 StreamWriter 在 C# 中写入文本文件,包括基本写入、追加、编码、格式化和异步操作。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直在撰写编程文章。到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程