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的主要方法
| 方法 | 说明 |
|---|---|
|
写字符串但不换行 |
|
写字符串并自动换行 |
|
强制把缓冲区写进文件(一般不用手动搞) |
/ |
关闭流并释放资源(using 会自动做) |
|
访问底层流(比如 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[文件一定被关闭]
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。
遇到 UnauthorizedAccessException 或 DirectoryNotFoundException:程序想保存到没权限的地方,或者文件夹根本不存在。记得检查路径和权限。
报错 "file is used by another process":你打开文件写但没关,或者有别的程序也在写。
GO TO FULL VERSION