ZetCode

在 C# 中读取文本文件

最后修改于 2025 年 4 月 22 日

本教程演示了在 C# 中读取文本文件的各种方法,重点介绍高效的基于流的技术。

在 C# 中,输入和输出操作依赖于流。Stream 类是所有流的抽象基类,表示来自文件、I/O 设备、进程间管道或 TCP/IP 套接字等源的字节序列。

C# 流

Stream 类为输入和输出提供了一个统一的接口,抽象掉了操作系统和设备特定的细节。例如,MemoryStream 处理内存中的数据,而 FileStream 管理基于文件的数据。

thermopylae.txt
The Battle of Thermopylae was fought between an alliance of Greek city-states,
led by King Leonidas of Sparta, and the Persian Empire of Xerxes I over the
course of three days, during the second Persian invasion of Greece.

本教程中的示例从这个示例文本文件读取数据。

使用 File.ReadLines 读取 C# 文本文件

File.ReadLines 方法返回文件中各行的 IEnumerable,并在迭代后关闭文件。 它具有内存效率,与一次加载全部内容的方法相比,非常适合大型文件。

Program.cs
using System.Text;

var path = "thermopylae.txt";

var enumLines = File.ReadLines(path, Encoding.UTF8);

foreach (var line in enumLines)
{
    Console.WriteLine(line);
}

此示例使用 foreach 循环迭代文件的行,并将每一行有效地打印到控制台。

使用 File.ReadAllLines 读取 C# 文本文件

File.ReadAllLines 方法将文本文件的所有行读入字符串数组并自动关闭文件。

注意:对于大型文件,由于其迭代方法,File.ReadLinesFile.ReadAllLines 更具内存效率。
Program.cs
using System.Text;

var path = "thermopylae.txt";

string[] lines = File.ReadAllLines(path, Encoding.UTF8);

foreach (string line in lines)
{
    Console.WriteLine(line);
}

此示例将整个 thermopylae.txt 文件读入字符串数组,并将每一行打印到控制台。

foreach (string line in lines)
{
    Console.WriteLine(line);
}

迭代字符串数组以显示每一行,从而处理文件在内存中的内容。

使用 File.ReadAllText 读取 C# 文本文件

File.ReadAllText 方法将文本文件的全部内容读入单个字符串并关闭文件。

注意:仅对小文件使用 File.ReadAllText,因为它会将整个文件加载到内存中,这对大型文件来说效率很低。
Program.cs
using System.Text;

var path = "thermopylae.txt";

string content = File.ReadAllText(path, Encoding.UTF8);
Console.WriteLine(content);

此示例将 thermopylae.txt 的完整内容读入字符串并将其输出到控制台。

使用 StreamReader 读取 C# 文本文件

StreamReader 类专为以特定编码读取字符数据而设计,针对逐行或完整处理文本文件进行了优化。

使用 StreamReader 的 ReadToEnd

ReadToEnd 方法读取从当前流位置到末尾的所有字符,并将内容作为字符串返回。

Program.cs
using System.Text;

var path = "thermopylae.txt";

using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
using var sr = new StreamReader(fs, Encoding.UTF8);

string content = sr.ReadToEnd();

Console.WriteLine(content);

此示例将 StreamReaderReadToEnd 结合使用,以通过 FileStream 读取整个文件内容。

using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);

FileStream 类创建用于文件操作的流,支持具有指定模式和权限的同步和异步访问。

using var sr = new StreamReader(fs, Encoding.UTF8);

FileStream 传递给 StreamReader,从而能够使用 UTF-8 编码读取文本。

string content = sr.ReadToEnd();

ReadToEnd 方法检索从流的当前位置到其末尾的所有字符。

使用 File.OpenRead

File.OpenRead 方法提供了一种创建用于读取的 FileStream 的便捷方法。

Program.cs
using System.Text;

var path = "thermopylae.txt";

using var fs = File.OpenRead(path);
using var sr = new StreamReader(fs, Encoding.UTF8);

string content = sr.ReadToEnd();

Console.WriteLine(content);

此示例使用 File.OpenRead 创建 FileStream,该 FileStreamStreamReader 使用 ReadToEnd 读取。

使用 StreamReader 的 ReadLine

ReadLine 方法从流中读取一行,将其作为字符串返回,非常适合逐行处理。

Program.cs
using System.Text;

var path = "thermopylae.txt";

using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
using var sr = new StreamReader(fs, Encoding.UTF8);

string line = String.Empty;

while ((line = sr.ReadLine()) != null)
{
    Console.WriteLine(line);
}

此示例使用 StreamReaderReadLine 方法逐行读取 thermopylae.txt

string line = String.Empty;

while ((line = streamReader.ReadLine()) != null)
{
        Console.WriteLine(line);
}

while 循环使用 ReadLine 读取每一行,将其打印出来,直到到达文件末尾。

使用 File.OpenText 读取 C# 文本

File.OpenText 方法打开一个用于读取的 UTF-8 编码的文本文件,简化了 StreamReader 的创建。

Program.cs
using System.Text;

var path = "thermopylae.txt";

using StreamReader sr = File.OpenText(path);
string content = sr.ReadToEnd();

Console.WriteLine(content);

此示例使用 File.OpenText 打开一个文本文件并使用 ReadToEnd 读取其内容。

使用 StreamReader 的 ReadToEndAsync 异步读取 C# 文本文件

ReadToEndAsync 方法异步读取从流的当前位置到其末尾的所有字符,并返回一个字符串。

Program.cs
using System.Text;

var path = "thermopylae.txt";

using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
using var sr = new StreamReader(fs, Encoding.UTF8);

string content = await sr.ReadToEndAsync();
Console.WriteLine(content);

此示例使用 ReadToEndAsync 异步读取文本文件,从而提高了 I/O 绑定操作的性能。

string content = await sr.ReadToEndAsync();

await 运算符暂停执行,直到异步 ReadToEndAsync 任务完成,确保非阻塞操作。

使用缓冲的 StreamReader 读取 C# 文本文件

此示例演示了如何使用具有自定义缓冲区大小的缓冲 StreamReader 读取大型文本文件,以优化性能。

Program.cs
using System.Text;

var path = "thermopylae.txt";

using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
using var sr = new StreamReader(fs, Encoding.UTF8, true, 1024);

string line;
while ((line = sr.ReadLine()) != null)
{
    Console.WriteLine(line);
}

此示例使用具有 1KB 缓冲区的 StreamReader 逐行读取 thermopylae.txt,从而优化了大型文件的内存使用。

使用异步 ReadLineAsync 读取 C# 文本文件

ReadLineAsync 方法异步读取一行,从而增强了 I/O 绑定应用程序中逐行处理的性能。

Program.cs
using System.Text;

var path = "thermopylae.txt";

using var fs = File.OpenRead(path);
using var sr = new StreamReader(fs, Encoding.UTF8);

string line;
while ((line = await sr.ReadLineAsync()) != null)
{
    Console.WriteLine(line);
}

此示例使用 ReadLineAsync 异步逐行读取 thermopylae.txt,从而确保高效的非阻塞 I/O。

使用 TextReader 读取 C# 文本文件

TextReader 类是 StreamReader 的基类,提供了一种读取文本的通用方法,可用于抽象文本源。

Program.cs
using System.Text;

var path = "thermopylae.txt";

using TextReader reader = File.OpenText(path);
string content = reader.ReadToEnd();

Console.WriteLine(content);

此示例通过 File.OpenText 使用 TextReader 读取整个 thermopylae.txt 文件,展示了一种灵活的文本读取方法。

使用错误处理读取 C# 文本文件

此示例展示了如何处理文件读取错误,确保通过适当的异常管理实现强大的文件 I/O 操作。

Program.cs
using System.Text;

var path = "thermopylae.txt";

try
{
    using var fs = File.OpenRead(path);
    using var sr = new StreamReader(fs, Encoding.UTF8);

    string content = sr.ReadToEnd();
    Console.WriteLine(content);
}
catch (FileNotFoundException)
{
    Console.WriteLine("Error: The file was not found.");
}
catch (IOException ex)
{
    Console.WriteLine($"Error reading file: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"Unexpected error: {ex.Message}");
}

此示例将文件读取包装在 try-catch 块中,处理诸如 FileNotFoundExceptionIOException 之类的特定异常,以确保可靠的错误报告。

来源

文件和流 I/O

本文探讨了在 C# 中读取文本文件的多种技术,包括同步和异步方法。

作者

我是 Jan Bodnar,一位经验丰富的软件开发程序员。 自 2007 年以来,我撰写了超过 1,400 篇编程文章和八本电子书。 凭借十多年的编程教学经验,我通过全面的教程分享我的专业知识。

列出所有 C# 教程