C# 文件的输入与输出

`File`、`Directory`、`StreamReader`/`StreamWriter`、以及 `Path`。

Intermediate
Key Points小文件用 `File.ReadAllText`,大文件用 `StreamReader` 逐行读。

一次性读写

C#
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}");
Output
第一行
第二行
第三行
字节数 26
行数 3

File.ReadAllText loads the whole file. Above tens of MB switch to streaming or risk OutOfMemoryException.

逐行读

C#
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);
}
Output
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.

写入

C#
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"));
Output
第一行
第二行
追加行

路径

C#
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);
Output
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
True
Always join paths with Path.Combine, never string concatenation — separators differ per platform. Also note Path.Combine("/a", "/b") yields /b: an absolute second argument wins.

目录

C#
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);
Output
True
目录 logs
文件 demo.txt
文件 out.txt
cs Program.cs

JSON 读写

C#
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());
Output
{
  "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.

Friends & Partners