C# 文件的输入与输出
`File`、`Directory`、`StreamReader`/`StreamWriter`、以及 `Path`。
一次性读写
using System.IO;
File.WriteAllText("demo.txt", "第一行\n第二行\n");
File.AppendAllText("demo.txt", "第三行\n");
var text = File.ReadAllText("demo.txt");
Console.Write(text);
Console.WriteLine($"字节数 {new FileInfo("demo.txt").Length}");
var lines = File.ReadAllLines("demo.txt");
Console.WriteLine($"行数 {lines.Length}");第一行
第二行
第三行
字节数 26
行数 3File.ReadAllText loads the whole file. Above tens of MB switch to streaming or risk OutOfMemoryException.
逐行读
using System.IO;
using var reader = new StreamReader("demo.txt");
string? line;
int n = 0;
while ((line = reader.ReadLine()) != null)
{
n++;
Console.WriteLine($"{n}: {line}");
}
// 或者用 File.ReadLines(惰性,不一次读入)
foreach (var l in File.ReadLines("demo.txt"))
{
if (l.Contains("第二")) Console.WriteLine("命中 " + l);
}1: 第一行
2: 第二行
3: 第三行
命中 第二行File.ReadLines is a lazy IEnumerable<string> that streams; File.ReadAllLines returns an array read up front. The former suits big files, the latter random access.
写入
using System.IO;
using (var writer = new StreamWriter("out.txt", append: false))
{
writer.WriteLine("第一行");
writer.WriteLine("第二行");
}
using var appender = new StreamWriter("out.txt", append: true);
appender.WriteLine("追加行");
Console.WriteLine(File.ReadAllText("out.txt"));第一行
第二行
追加行路径
using System.IO;
var p = Path.Combine("data", "2026", "a.txt");
Console.WriteLine(p);
Console.WriteLine(Path.GetFileName(p));
Console.WriteLine(Path.GetExtension(p));
Console.WriteLine(Path.GetDirectoryName(p));
Console.WriteLine(Path.GetFullPath(p));
Console.WriteLine(Path.GetTempPath());
var f = new FileInfo("demo.txt");
Console.WriteLine(f.Exists);
Console.WriteLine(f.Length);
Console.WriteLine(f.LastWriteTime.Year > 2000);data\2026\a.txt
a.txt
.txt
data\2026
C:\Users\Administrator\demo\data\2026\a.txt
C:\Users\Administrator\AppData\Local\Temp\
True
26
TruePath.Combine, never string concatenation — separators differ per platform. Also note Path.Combine("/a", "/b") yields /b: an absolute second argument wins.目录
using System.IO;
Directory.CreateDirectory("logs/2026");
Console.WriteLine(Directory.Exists("logs"));
foreach (var dir in Directory.GetDirectories("."))
{
Console.WriteLine("目录 " + Path.GetFileName(dir));
}
foreach (var file in Directory.GetFiles(".", "*.txt"))
{
Console.WriteLine("文件 " + Path.GetFileName(file));
}
// 递归枚举(惰性)
foreach (var f in Directory.EnumerateFiles(".", "*.cs", SearchOption.AllDirectories).Take(3))
{
Console.WriteLine("cs " + Path.GetFileName(f));
}
// 删除(recursive: true 会连子目录一起删)
// Directory.Delete("logs", recursive: true);True
目录 logs
文件 demo.txt
文件 out.txt
cs Program.csJSON 读写
using System.Text.Json;
var user = new { Name = "张三", Age = 28, Tags = new[] { "a", "b" } };
var json = JsonSerializer.Serialize(user, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText("user.json", json);
Console.WriteLine(File.ReadAllText("user.json"));
var back = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json)!;
Console.WriteLine(back["Name"].GetString());{
"Name": "\u5F20\u4E09",
"Age": 28,
"Tags": [
"a",
"b"
]
}
张三System.Text.Json escapes non-ASCII as \uXXXX by default. For raw Chinese set Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping — only for trusted output.
一次性读写
using System.IO;
File.WriteAllText("demo.txt", "第一行\n第二行\n");
File.AppendAllText("demo.txt", "第三行\n");
var text = File.ReadAllText("demo.txt");
Console.Write(text);
Console.WriteLine($"字节数 {new FileInfo("demo.txt").Length}");
var lines = File.ReadAllLines("demo.txt");
Console.WriteLine($"行数 {lines.Length}");第一行
第二行
第三行
字节数 26
行数 3File.ReadAllText 会把整个文件读进内存。文件超过几十 MB 就该用流式读取,否则容易 OutOfMemoryException。
逐行读
using System.IO;
using var reader = new StreamReader("demo.txt");
string? line;
int n = 0;
while ((line = reader.ReadLine()) != null)
{
n++;
Console.WriteLine($"{n}: {line}");
}
// 或者用 File.ReadLines(惰性,不一次读入)
foreach (var l in File.ReadLines("demo.txt"))
{
if (l.Contains("第二")) Console.WriteLine("命中 " + l);
}1: 第一行
2: 第二行
3: 第三行
命中 第二行File.ReadLines 返回惰性 IEnumerable<string>,边读边给;File.ReadAllLines 返回数组,一次全读。前者适合大文件,后者适合要随机访问。
写入
using System.IO;
using (var writer = new StreamWriter("out.txt", append: false))
{
writer.WriteLine("第一行");
writer.WriteLine("第二行");
}
using var appender = new StreamWriter("out.txt", append: true);
appender.WriteLine("追加行");
Console.WriteLine(File.ReadAllText("out.txt"));第一行
第二行
追加行路径
using System.IO;
var p = Path.Combine("data", "2026", "a.txt");
Console.WriteLine(p);
Console.WriteLine(Path.GetFileName(p));
Console.WriteLine(Path.GetExtension(p));
Console.WriteLine(Path.GetDirectoryName(p));
Console.WriteLine(Path.GetFullPath(p));
Console.WriteLine(Path.GetTempPath());
var f = new FileInfo("demo.txt");
Console.WriteLine(f.Exists);
Console.WriteLine(f.Length);
Console.WriteLine(f.LastWriteTime.Year > 2000);data\2026\a.txt
a.txt
.txt
data\2026
C:\Users\Administrator\demo\data\2026\a.txt
C:\Users\Administrator\AppData\Local\Temp\
True
26
TruePath.Combine**,不要用字符串 +。Windows 用 \、Linux 用 /,手拼的路径换平台就废。而且要小心:Path.Combine("/a", "/b") 结果是 /b——绝对路径会覆盖前面的部分。目录
using System.IO;
Directory.CreateDirectory("logs/2026");
Console.WriteLine(Directory.Exists("logs"));
foreach (var dir in Directory.GetDirectories("."))
{
Console.WriteLine("目录 " + Path.GetFileName(dir));
}
foreach (var file in Directory.GetFiles(".", "*.txt"))
{
Console.WriteLine("文件 " + Path.GetFileName(file));
}
// 递归枚举(惰性)
foreach (var f in Directory.EnumerateFiles(".", "*.cs", SearchOption.AllDirectories).Take(3))
{
Console.WriteLine("cs " + Path.GetFileName(f));
}
// 删除(recursive: true 会连子目录一起删)
// Directory.Delete("logs", recursive: true);True
目录 logs
文件 demo.txt
文件 out.txt
cs Program.csJSON 读写
using System.Text.Json;
var user = new { Name = "张三", Age = 28, Tags = new[] { "a", "b" } };
var json = JsonSerializer.Serialize(user, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText("user.json", json);
Console.WriteLine(File.ReadAllText("user.json"));
var back = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json)!;
Console.WriteLine(back["Name"].GetString());{
"Name": "\u5F20\u4E09",
"Age": 28,
"Tags": [
"a",
"b"
]
}
张三System.Text.Json 默认会把非 ASCII 字符转成 \uXXXX。要输出中文原文,设置 Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping(注意只在可信输出里用)。