CodeGym /课程 /C# SELF /写入文本文件: StreamWriter...

写入文本文件: StreamWriter

C# SELF
第 36 级 , 课程 3
可用

1. 入门

StreamWriter 是 .NET 里 System.IO 命名空间下的一个核心类,用来通过流方便地把文本数据写进文件。

为啥不能直接用 FileStream
FileStream 只能操作字节。如果你想直接写字符串,就得自己把文本转成字节,还得管编码(你迟早会想回到 StreamWriter)。
StreamWriter 会帮你搞定这些麻烦:你给它字符串——它自动写对的字节进文件。

主要优点:

  • 写字符串超简单,不用管怎么转成字节。
  • 有按行写文本的方法。
  • 可以控制缓冲和编码(后面会教你怎么玩)。

最简单的例子

using System.IO;

string path = "output.txt";

using (StreamWriter writer = new StreamWriter(path))
{
    writer.WriteLine("你好,世界!");
    writer.WriteLine("这是第二行。");
}
// 出了using大括号后,StreamWriter一定会释放文件。

这里发生了啥?

  • 打开文件准备写(如果没有文件会自动创建)。
  • 每一行都作为文件里的新行写进去(用 WriteLine 方法)。
  • 出了 using 块后,文件会自动关闭,就算出错也没事。

如果你运行完这个程序再打开 output.txt 文件,就能看到两行文本,和你写的一样。

重要细节

如果文件已经存在,它会被从头覆盖!原来的内容全没了。所以要小心:别把重要论文或者唯一的水电账单放这种文件里。

2. 向流写数据

StreamWriter的主要方法

方法 说明
Write(string)
写字符串但不换行
WriteLine(string)
写字符串并自动换行
Flush()
强制把缓冲区写进文件(一般不用手动搞)
Close()
/
Dispose()
关闭流并释放资源(using 会自动做)
BaseStream
访问底层流(比如 FileStream)

Write() 方法

写数据但不换行。你后面写的内容都会在同一行里。

WriteLine() 方法

写数据并自动加上换行符(Windows下是 \r\n,类Unix系统下是 \n)。
就像你每次写完按一下回车。

Write() vs WriteLine():区别演示

using (var writer = new StreamWriter("example.txt"))
{
    writer.Write("第一段 ");
    writer.Write("段落。 ");
    writer.WriteLine("补充一行,回车!");
    writer.Write("第二段。");
}

现在 example.txt 文件大概长这样:

第一段 段落。 补充一行,回车!
第二段。

3. 编码的用法

默认情况下,如果你创建 StreamWriter 没指定参数,会用 UTF-8 带BOM(字节顺序标记)的编码。

这很现代也很方便,但有时候你得手动指定编码——比如要兼容老软件或者导入某些数据。

怎么指定编码?

// 用Windows-1251编码写文件(老系统的西里尔文)
using (var writer = new StreamWriter("cyrillic.txt", false, System.Text.Encoding.GetEncoding("windows-1251")))
{
    writer.WriteLine("你好,西里尔世界!");
}

注意:
编码得系统支持才行。如果不确定——就用 UTF-8 吧。

4. 构造函数的其他参数

来看看 StreamWriter 的内部参数:

public StreamWriter(
    string path,              // 文件路径
    bool append = false,      // 追加到文件末尾?
    Encoding encoding = null, // 编码
    int bufferSize = 1024     // 缓冲区大小,字节
)
  • append —— 如果 false(默认),文件会被覆盖。如果 true,新内容会加到末尾。
  • encoding —— 用的编码。
  • bufferSize —— 内部缓冲区大小,写大数据时能加速。

例子:往同一个文件追加内容

// 文件会被追加,不会覆盖
using (var writer = new StreamWriter("log.txt", append: true))
{
    writer.WriteLine(DateTime.Now + " -- 新事件");
}

5. 实用细节

追加和覆盖时会发生什么

模式 干了啥? 文件结果
append: false 全部覆盖 旧数据全没了
append: true 新行加到末尾 旧行还在

小提示: 追加模式(append: true)超适合做日志,能保存事件历史。

StreamWriter和大数据量

  • StreamWriter 会缓冲写入:你 WriteLine 后,数据其实稍后才进文件。但关闭流(或手动 Flush())后,一定会写到磁盘。
  • WriteLine 按行写很高效。要写复杂格式(比如JSON、CSV或XML),最好用专门的库,或者自己小心转义特殊字符(比如逗号或引号)。

怎么正确结束写入并释放资源

正确姿势: 一定要用 using
这样就算出异常(比如磁盘爆了或者文件被别的程序锁住),文件也会被关闭。


flowchart TD
    A[创建 StreamWriter] --> B[操作文件]
    B --> C{异常?}
    C -- 是 --> D[会调用 Dispose]
    C -- 否 --> D
    D --> E[文件一定被关闭]
图示: using 就算出错也能保证文件被关闭

6. 实战例子

假如我们这门课有个小型图书管理程序。现在加个功能,把新书写进文件。

例子:把新书保存到单独文件

using System;
using System.IO;

class Program
{
    static void Main()
    {
        Console.WriteLine("请输入书名:");
        string bookTitle = Console.ReadLine();

        Console.WriteLine("请输入作者:");
        string author = Console.ReadLine();

        string path = "books.txt";
        using (var writer = new StreamWriter(path, append: true))
        {
            writer.WriteLine($"{bookTitle};{author}");
            // CSV格式:每行一书,用分号分隔
        }

        Console.WriteLine("书已保存到文件!");
    }
}

你可以试着连续加几本书。books.txt 文件里的内容会一直追加,不会覆盖前面的。这个方式很适合做日志或者记录——比如你以后做企业级开发时的审计系统。

7. 怎么避免写文件时的常见坑

新手最常遇到这些问题:

文件没关,被别的进程锁住。原因——忘了用 using

写了好多行但文件还是空的:忘了 Flush() 或没关流(用 using 就自动搞定)。

不小心覆盖了文件没追加——忘了写 append: true

编码问题:文件在记事本里全是乱码——选错了编码,或者别的程序不支持 UTF-8

遇到 UnauthorizedAccessExceptionDirectoryNotFoundException:程序想保存到没权限的地方,或者文件夹根本不存在。记得检查路径和权限。

报错 "file is used by another process":你打开文件写但没关,或者有别的程序也在写。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION