C# 文本文件的读写(超详细)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

在编程开发中,文本文件的读写是一项基础但至关重要的技能。无论是日志记录、数据配置,还是用户交互,C# 提供了多种简洁高效的方法来实现文本文件的读写操作。对于编程初学者而言,理解如何与文件系统交互是迈向成熟开发的关键一步;而中级开发者则可以通过掌握高级技巧,进一步优化代码性能和健壮性。本文将从基础概念出发,结合实际案例,深入讲解 C# 文本文件的读写 过程,帮助读者逐步构建系统的知识框架。


2.1 基础概念:文件读写的底层逻辑

文件读写的核心流程

文本文件的读写本质上是程序与文件系统的交互过程。其核心流程可分为四步:

  1. 打开文件:建立程序与文件的连接。
  2. 读写数据:根据需求读取或写入数据。
  3. 关闭连接:释放系统资源,确保数据完整保存。
  4. 异常处理:捕获并解决可能出现的错误(如文件不存在或权限不足)。

比喻理解:文件读写如同“快递服务”

可以将文件读写想象成快递服务:

  • 打开文件:如同快递员联系收件人确认地址。
  • 读写数据:如同打包或拆开包裹。
  • 关闭文件:如同完成签收并结束服务。
  • 异常处理:如同处理地址错误或包裹损坏的情况。

2.2 核心类与方法:C# 的文件操作工具箱

C# 提供了多个类和方法来简化文件操作,以下是常用的工具:

File 类:快速完成简单操作

System.IO.File 类提供了静态方法,适合执行单次读写操作。例如:

// 写入文本  
File.WriteAllText("example.txt", "Hello, World!");  

// 读取文本  
string content = File.ReadAllText("example.txt");  

特点

  • 简单直接:无需手动管理流(Stream)或关闭文件。
  • 适用场景:小文件或一次性操作。

StreamReader/StreamWriter:流式操作的灵活性

当需要逐行读写或处理大文件时,StreamReaderStreamWriter 更合适:

using (StreamWriter writer = new StreamWriter("log.txt"))  
{  
    writer.WriteLine("日志记录:操作成功");  
}  

using (StreamReader reader = new StreamReader("log.txt"))  
{  
    string line;  
    while ((line = reader.ReadLine()) != null)  
    {  
        Console.WriteLine(line);  
    }  
}  

特点

  • 流式处理:支持逐行读写,适合处理大数据或动态内容。
  • 资源管理:通过 using 语句自动释放资源。

FileInfo 类:面向对象的文件操作

FileInfo 以对象形式封装文件属性和方法,适合需要频繁操作单个文件的场景:

FileInfo fileInfo = new FileInfo("data.txt");  

// 创建文件(若不存在)  
if (!fileInfo.Exists)  
{  
    fileInfo.Create();  
}  

// 写入文本  
using (StreamWriter writer = fileInfo.AppendText())  
{  
    writer.WriteLine("新增内容");  
}  

特点

  • 面向对象:方法与属性直接绑定到文件对象。
  • 扩展性:可轻松集成其他文件操作(如重命名或删除)。

2.3 进阶技巧:优化与异常处理

异步操作:提升程序响应速度

对于大文件或长时间操作,异步方法可避免阻塞主线程:

// 异步写入  
await File.WriteAllTextAsync("async.txt", "异步内容");  

// 异步读取  
string asyncContent = await File.ReadAllTextAsync("async.txt");  

优势

  • 非阻塞:在等待 I/O 操作时,程序可继续执行其他任务。
  • 适用场景:GUI 应用或高并发服务器环境。

异常处理:优雅地应对错误

通过 try-catch 块捕获常见异常,并提供用户友好的提示:

try  
{  
    string content = File.ReadAllText("不存在的文件.txt");  
}  
catch (FileNotFoundException)  
{  
    Console.WriteLine("错误:文件未找到,请检查路径。");  
}  
catch (IOException)  
{  
    Console.WriteLine("错误:文件被占用或权限不足。");  
}  

2.4 实际案例:日志记录系统

场景描述

假设我们需要为一个应用程序创建日志记录功能,要求:

  • 按日期自动创建日志文件。
  • 每次记录追加到文件末尾。
  • 处理可能的写入异常。

实现代码

public static void LogMessage(string message)  
{  
    string logPath = $"logs/{DateTime.Now:yyyy-MM-dd}.log";  

    try  
    {  
        using (StreamWriter writer = new StreamWriter(logPath, true))  
        {  
            writer.WriteLine($"{DateTime.Now:HH:mm:ss} - {message}");  
        }  
    }  
    catch (Exception ex)  
    {  
        // 简单示例中直接输出错误,实际应用可记录到控制台或事件日志  
        Console.WriteLine($"日志写入失败:{ex.Message}");  
    }  
}  

// 使用示例  
LogMessage("用户登录成功");  

代码解析

  • 路径动态生成:使用 DateTime 根据日期生成文件名。
  • 追加模式StreamWriter 的第二个参数 true 表示追加内容。
  • 异常捕获:确保程序在写入失败时不会崩溃,同时提示错误原因。

2.5 性能优化:流与缓冲区的妙用

缓冲区:流式操作的“蓄水池”

StreamReaderStreamWriter 内部使用缓冲区来减少磁盘 I/O 次数。例如:

using (StreamWriter writer = new StreamWriter("large.txt", false, Encoding.UTF8, 1024 * 1024))  
{  
    // 缓冲区大小设为 1MB,适合处理大文件  
}  

原理

  • 内存缓存:数据先写入内存缓冲区,达到一定量后再一次性写入磁盘。
  • 优势:显著减少磁盘访问次数,提升性能。

批量操作:减少文件打开/关闭的次数

频繁打开和关闭文件会降低性能,应尽量合并操作:

// 低效写法  
for (int i = 0; i < 1000; i++)  
{  
    File.AppendAllText("data.txt", $"{i}\n");  
}  

// 高效写法  
using (StreamWriter writer = new StreamWriter("data.txt", true))  
{  
    for (int i = 0; i < 1000; i++)  
    {  
        writer.WriteLine(i);  
    }  
}  

2.6 常见问题与解决方案

问题 1:文件被占用导致写入失败

原因:其他程序或进程正在使用该文件。
解决方案

  • 确保文件未被其他程序打开。
  • 使用 FileShare 参数允许共享访问(需谨慎)。

问题 2:读取非 UTF-8 编码的文件出现乱码

原因:文件使用了不同的编码格式(如 GB2312)。
解决方案

// 指定编码格式  
byte[] bytes = File.ReadAllBytes("gbk_file.txt");  
string content = Encoding.GetEncoding("GB2312").GetString(bytes);  

问题 3:写入大量数据时内存不足

解决方案

  • 使用流式操作逐行处理。
  • 分批次写入,避免一次性加载全部数据。

结论

通过本文的学习,读者应已掌握 C# 文本文件的读写 的核心方法、进阶技巧以及实际应用案例。从基础的 File 类到灵活的流操作,再到性能优化和异常处理,这些知识将帮助开发者高效、安全地与文件系统交互。

关键总结

  1. 根据需求选择合适的类(File、StreamReader/StreamWriter 或 FileInfo)。
  2. 始终使用 using 语句或 try-finally 确保资源释放。
  3. 对于复杂场景,优先考虑异步操作和缓冲区优化。

希望读者能通过实践不断巩固这些技能,并在实际项目中灵活应用。

最新发布