在软件开发中,文件的输入输出(I/O)操作是基础且常见的任务。C# 提供了强大的文件操作接口,允许我们轻松地读写文件、管理文件系统等。在本篇文章中,我们将深入探讨 C# 中的文件 I/O 操作,重点介绍常用的 I/O 类、FileStream 的使用以及高级文件操作技巧。
什么是文件和流?
文件概念
文件是存储在磁盘上的一组数据,包含了各种不同的内容,如文本、图像、音频等。每个文件都有一个名称和路径,且可以通过文件系统进行访问。在 C# 中,文件操作通常是通过流来实现的。
流的概念
流(Stream)是字节或字符数据在内存、文件、网络等介质之间传输的抽象概念。流可以分为输入流(读取数据)和输出流(写入数据)。
在 C# 中,System.IO 命名空间提供了多种流类,来帮助我们实现文件的读写。文件操作主要是通过文件流(FileStream)、字符流(StreamReader, StreamWriter)和二进制流(BinaryReader, BinaryWriter)来完成的。
C# 中的 I/O 类
在 C# 中,System.IO 命名空间提供了各种类来执行文件操作。以下是一些常用的类及其作用:
| I/O 类 | 描述 |
|---|---|
| BinaryReader | 从二进制流中读取原始数据。 |
| BinaryWriter | 以二进制格式写入原始数据。 |
| BufferedStream | 提供字节流的临时缓冲存储。 |
| Directory | 用于操作目录结构(创建、删除、遍历等)。 |
| File | 提供文件的基本操作(复制、删除、重命名等)。 |
| FileStream | 用于读取和写入文件流,支持文件的随机访问。 |
| MemoryStream | 用于处理存储在内存中的数据流。 |
| StreamReader | 用于从字节流中读取字符数据。 |
| StreamWriter | 用于向流中写入字符数据。 |
FileStream 类详解
FileStream 是最常用的文件流类之一,允许我们对文件进行高效的读取和写入操作。它继承自抽象类 Stream,可以实现对文件的随机访问操作。通过 FileStream,我们可以精确控制文件流的打开模式、读取/写入权限以及文件共享方式。
创建 FileStream 对象
创建 FileStream 对象时,我们需要指定以下几个关键参数:
FileStream fs = new FileStream("test.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
-
FileMode:定义文件的打开模式,例如:
Create:创建新文件,若文件已存在则覆盖。Open:打开已存在的文件,文件不存在会抛出异常。Append:打开文件并将内容追加到文件末尾。
-
FileAccess:指定文件的访问权限:
Read:只能读取文件。Write:只能写入文件。ReadWrite:同时支持读取和写入文件。
-
FileShare:定义文件的共享方式,控制其他进程如何访问该文件:
None:不允许其他进程访问该文件。Read:允许其他进程读取文件。ReadWrite:允许其他进程读取和写入文件。
示例:基本的 FileStream 操作
using System;
using System.IO;
namespace FileIOExample
{
class Program
{
static void Main(string[] args)
{
// 创建 FileStream 对象,打开或创建文件
using (FileStream fs = new FileStream("test.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
// 写入数据
for (int i = 1; i <= 20; i++)
{
fs.WriteByte((byte)i);
}
// 设置文件指针为文件开头
fs.Position = 0;
// 读取并打印数据
for (int i = 0; i < 20; i++)
{
Console.Write(fs.ReadByte() + " ");
}
}
Console.ReadKey();
}
}
}
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 -1
-1 表示文件结尾的标识符,意味着已读取完所有数据。
代码解析:
- FileStream 创建:通过
new FileStream("test.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite)创建一个文件流对象。如果文件不存在,则自动创建。 - 数据写入:利用
fs.WriteByte()方法逐个写入数据。 - 文件指针控制:通过设置
fs.Position属性将文件指针重置到文件开头。 - 数据读取:使用
fs.ReadByte()逐个读取字节并打印,直到读取完文件为止。 - 自动关闭文件流:通过
using语句确保文件流在使用完毕后自动关闭,避免资源泄漏。
C# 高级文件操作
1. 文本文件的读写
如果你需要读取或写入文本文件,StreamReader 和 StreamWriter 是非常合适的选择。它们提供了更方便的字符流操作接口。
using (StreamReader reader = new StreamReader("textfile.txt"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
using (StreamWriter writer = new StreamWriter("textfile.txt", true))
{
writer.WriteLine("Appending a new line.");
}
2. 二进制文件的读写
如果需要处理二进制文件(如图像、音频等),则可以使用 BinaryReader 和 BinaryWriter。
using (BinaryReader reader = new BinaryReader(File.Open("data.bin", FileMode.Open)))
{
int intValue = reader.ReadInt32();
Console.WriteLine("Read integer: " + intValue);
}
using (BinaryWriter writer = new BinaryWriter(File.Open("data.bin", FileMode.Create)))
{
writer.Write(12345);
}
3. 文件性能优化
在处理大文件时,我们需要关注性能问题。为了提高文件操作的效率,可以使用 BufferedStream 来缓存字节流,从而减少 I/O 操作的次数。
using (BufferedStream bufferedStream = new BufferedStream(new FileStream("largefile.dat", FileMode.Open)))
{
int byteRead;
while ((byteRead = bufferedStream.ReadByte()) != -1)
{
// 处理字节数据
}
}
4. 异常处理
文件操作时,常见的异常包括文件不存在、权限不足、磁盘空间不足等。在进行文件操作时,应使用 try-catch 语句进行异常捕获。
try
{
using (FileStream fs = new FileStream("nonexistent.txt", FileMode.Open))
{
// 执行操作
}
}
catch (FileNotFoundException ex)
{
Console.WriteLine("Error: File not found.");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("Error: Access denied.");
}
总结与最佳实践
C# 提供了丰富的文件操作类,让文件的读写变得非常方便和高效。我们可以利用 FileStream、StreamReader、StreamWriter、BinaryReader 等类来处理不同类型的文件。在实际应用中,我们还需要关注性能优化、异常处理和文件权限等问题。掌握这些文件操作技巧,将
👋 关注我!持续分享 C# 实战技巧、代码示例 & 技术干货

被折叠的 条评论
为什么被折叠?



