VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#编程 >
  • 文件读写:StreamReader/StreamWriter

文件读写:StreamReader/StreamWriter
概述
StreamReader和StreamWriter是处理文本文件的核心类,属于System.IO命名空间。它们基于字符流操作,自动完成字节与字符的编码转换,支持不同字符编码(如UTF-8、GBK),是读写文本文件的首选工具。
StreamReader:从文件中读取字符流,支持逐vb.net教程C#教程python教程SQL教程access 2010教程
行读取、全部读取等操作;
StreamWriter:向文件中写入字符流,支持追加写入、指定编码等操作;
核心优势:灵活控制编码和缓冲区,适合处理大文件(逐行读取不占用过多内存);
资源管理:实现IDisposable接口,必须手动释放资源(推荐用using语句自动处理)。

  1. 实例代码:完整的文件读写流程
    以下实例模拟日志文件的写入与读取,包含创建文件、写入内容、追加内容、逐行读取、全部读取等操作:
    csharp
	using System;
	using System.IO; // 必须引用
	using System.Text; // 编码相关
	
	class FileIOExample {
	static void Main() {
	string logPath = "app.log"; // 日志文件路径
	
	// -------------------------- 1. 写入日志文件(覆盖模式) --------------------------
	// using语句:自动释放StreamWriter资源,即使发生异常
	using (StreamWriter writer = new StreamWriter(logPath, false, Encoding.UTF8)) {
	writer.WriteLine("【2025-12-05 10:00:00】系统启动成功");
	writer.WriteLine("【2025-12-05 10:05:00】用户登录:admin");
	writer.Write("【2025-12-05 10:10:00】操作类型:"); // Write不自动换行
	writer.WriteLine("修改密码");
	} // using结束时自动调用writer.Dispose(),关闭文件流
	
	Console.WriteLine("日志文件写入完成!
");
	
	// -------------------------- 2. 读取日志文件(全部读取) --------------------------
	using (StreamReader reader = new StreamReader(logPath, Encoding.UTF8)) {
	string allContent = reader.ReadToEnd(); // 一次性读取所有内容
	Console.WriteLine("日志文件全部内容:
" + allContent);
	}
	
	Console.WriteLine("
--------------------------
");
	
	// -------------------------- 3. 追加日志内容 --------------------------
	using (StreamWriter writer = new StreamWriter(logPath, true, Encoding.UTF8)) { // true表示追加
	writer.WriteLine("【2025-12-05 10:15:00】用户退出:admin");
	}
	
	// -------------------------- 4. 逐行读取日志(适合大文件) --------------------------
	Console.WriteLine("追加后的日志(逐行读取):");
	using (StreamReader reader = new StreamReader(logPath, Encoding.UTF8)) {
	string line;
	// 逐行读取,直到null(文件结束)
	while ((line = reader.ReadLine()) != null) {
	Console.WriteLine("- " + line);
	}
	}
	}
	}
  1. 逐行讲解
    2.1 写入文件部分
    csharp
	using (StreamWriter writer = new StreamWriter(logPath, false, Encoding.UTF8)) {
	writer.WriteLine("【2025-12-05 10:00:00】系统启动成功");
	writer.Write("【2025-12-05 10:10:00】操作类型:"); 
	writer.WriteLine("修改密码");
	}

using语句:自动调用Dispose()方法释放资源,避免文件被占用;
StreamWriter构造参数:
ologPath:文件路径(不存在则创建,存在则覆盖/追加);
ofalse:是否追加?false=覆盖原有内容,true=追加到末尾;
oEncoding.UTF8:指定字符编码(避免中文乱码);
WriteLine vs Write:WriteLine自动添加换行符( ),Write不添加。
2.2 全部读取部分
csharp

	using (StreamReader reader = new StreamReader(logPath, Encoding.UTF8)) {
	string allContent = reader.ReadToEnd();
	Console.WriteLine("日志文件全部内容:
" + allContent);
	}

StreamReader构造参数:Encoding.UTF8必须与写入时一致,否则会乱码;
ReadToEnd():一次性读取所有内容,适合小文件(大文件会占用过多内存)。
2.3 追加内容部分
csharp

	using (StreamWriter writer = new StreamWriter(logPath, true, Encoding.UTF8)) {
	writer.WriteLine("【2025-12-05 10:15:00】用户退出:admin");
	}

true参数:表示追加模式,新内容会写在文件末尾,不会覆盖原有内容;
编码一致性:必须与原文件编码相同,否则追加的内容会乱码。
2.4 逐行读取部分
csharp

	using (StreamReader reader = new StreamReader(logPath, Encoding.UTF8)) {
	string line;
	while ((line = reader.ReadLine()) != null) {
	Console.WriteLine("- " + line);
	}
	}

ReadLine():每次读取一行内容,返回null表示文件结束;
适合场景:大文件(如1GB日志),逐行读取不会占用过多内存;
循环逻辑:line = reader.ReadLine()先执行读取,再判断是否为null。

  1. 基础知识拓展
    3.1 编码的重要性
    编码是字节与字符的映射规则,错误的编码会导致乱码:
    常见编码:
    oUTF-8:国际通用,支持所有语言,文件开头可能有BOM(字节顺序标记);
    oGBK:中文系统常用,仅支持中文和英文;
    oUnicode:固定2字节,占用空间大;
    示例:用GBK编码写入的文件,用UTF-8读取会显示乱码,反之亦然。
    正确用法:写入和读取必须使用相同编码,推荐使用UTF-8(无BOM):
    csharp
	// 无BOM的UTF-8编码
	Encoding utf8NoBom = new UTF8Encoding(false); 
	using (StreamWriter writer = new StreamWriter(logPath, false, utf8NoBom)) { ... }

3.2 流的层次关系
StreamReader/StreamWriter是字符流,基于字节流(FileStream)封装:
字节流:处理原始字节(如FileStream、MemoryStream);
字符流:处理字符(如StreamReader/StreamWriter),自动转换字节到字符;
关系:StreamReader内部包装了FileStream,通过编码将字节转换为字符。
示例:手动创建字节流并包装为字符流(等价于StreamReader):
csharp

	using (FileStream fs = new FileStream(logPath, FileMode.Open)) {
	using (StreamReader reader = new StreamReader(fs, Encoding.UTF8)) {
	string content = reader.ReadToEnd();
	}
	}

3.3 性能优化
缓冲区大小:StreamReader/StreamWriter默认缓冲区大小为4096字节(4KB),可手动指定更大的缓冲区提升大文件读写速度:
csharp

	// 缓冲区大小为8KB
	using (StreamWriter writer = new StreamWriter(logPath, false, Encoding.UTF8, 8192)) { ... }

避免一次性读取:大文件用ReadLine()逐行读取,小文件用ReadToEnd();
关闭流:即使使用using语句,也可手动调用Close()方法(内部会调用Dispose())。
3.4 与File类的区别
File类提供了快捷方法(如File.ReadAllText、File.WriteAllText),但StreamReader/StreamWriter更灵活:

特性 StreamReader/StreamWriter File类快捷方法(如ReadAllText)

总结:小文件用File类快捷方法,大文件或复杂操作(如追加、逐行读写)用StreamReader/StreamWriter。
3.5 异常处理
文件操作容易抛出异常,必须用try-catch处理:
csharp

	try {
	using (StreamReader reader = new StreamReader("nonexistent.txt")) { ... }
	} catch (FileNotFoundException ex) {
	Console.WriteLine("文件不存在:" + ex.Message);
	} catch (UnauthorizedAccessException ex) {
	Console.WriteLine("权限不足:" + ex.Message);
	} catch (Exception ex) {
	Console.WriteLine("未知错误:" + ex.Message);
	}
  1. 常见问题与解决
    中文乱码:确保写入和读取的编码一致(如UTF-8);
    文件被占用:未释放资源导致,必须用using语句或手动调用Dispose();
    大文件内存溢出:用ReadLine()逐行读取,而非ReadToEnd();
    追加内容乱码:追加时编码必须与原文件一致。

总结
StreamReader/StreamWriter是处理文本文件的核心工具,掌握它们的用法能解决90%以上的文本文件操作需求。关键要点:
用using语句管理资源;
保持写入和读取的编码一致;
大文件用逐行读取,小文件用一次性读取;
灵活使用追加模式和编码控制。
下一章:二进制文件读写:BinaryReader/BinaryWriter
(深入讲解二进制文件的读写操作,适合处理非文本文件如图片、音频等)
(本节完)

本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49386.html


相关教程