本章主要介绍文件的操作,通常被称为I/O,即输入输出。对文件的操作是大部分应用程序所要面临的基础性工作,这些操作包括文件的创建、删除、读写、更新等。本章将会对这些内容进行逐一的介绍,使读者对.NET框架下的I/O操作有一个大致的了解。同时,给出相应的代码实例,使读者有一个直观的认识。
本章主要内容
& 如何使用System.IO命名空间下的类
& 如何访问文件
& 如何访问文件夹
& File类和FileInfo类的区别和联系
& Directory类和DirectoryInfo类的区别和联系
& 如何进行流操作
& 如何向文件进行写入操作
& 如何写入二进制值
文件与前文介绍的数组等变量不同,变量中的数据只是在程序运行时存在,随着程序的终结,变量的内容也随之丢失。而文件中的内容可以永久地存储数据到硬盘或其他设备上,这就是通常所说的持久性数据。文件的这种特性可以使开发人员方便地存储应用程序配置等数据,以便在程序下一次运行时使用。
System.IO命名空间包含了所有本章所要介绍的输入输出类。下面先对System.IO类进行简要的介绍,使读者有一个更直观的了解。表9-1列出了System.IO下的所有类。
表9-1 System.IO类列表
类 名 |
说 明 |
BinaryReader |
用特定的编码将基元数据类型读作二进制值 |
BinaryWriter |
以二进制形式将基元类型写入流,并支持用特定的编码写入字符串 |
BufferedStream |
给另一流上的读写操作添加一个缓冲层。无法继承此类 |
Directory |
公开用于创建、移动和枚举通过目录和子目录的静态方法。无法继承此类 |
DirectoryInfo |
公开用于创建、移动和枚举目录和子目录的实例方法。无法继承此类 |
DirectoryNotFoundException |
当找不到文件或目录的一部分时所引发的异常 |
DriveInfo |
提供对有关驱动器的信息的访问 |
DriveNotFoundException |
当尝试访问的驱动器或共享不可用时引发的异常 |
EndOfStreamException |
读操作试图超出流的末尾时引发的异常 |
ErrorEventArgs |
为Error事件提供数据 |
File |
提供用于创建、复制、删除、移动和打开文件的静态方法,并协助创建FileStream对象 |
FileInfo |
提供创建、复制、删除、移动和打开文件的实例方法,并且帮助创建FileStream对象。无法继承此类 |
FileLoadException |
当找到托管程序集却不能加载它时引发的异常 |
FileNotFoundException |
试图访问磁盘上不存在的文件失败时引发的异常 |
FileStream |
公开以文件为主的Stream,既支持同步读写操作,也支持异步读写操作 |
FileSystemEventArgs |
提供目录事件的数据:Changed、Created、Deleted |
FileSystemInfo |
为FileInfo和DirectoryInfo对象提供基类 |
FileSystemWatcher |
侦听文件系统更改通知,并在目录或目录中的文件发生更改时引发事件 |
InternalBufferOverflowException |
内部缓冲区溢出时引发的异常 |
InvalidDataException |
在数据流的格式无效时引发的异常 |
IODescriptionAttribute |
设置可视化设计器在引用事件、扩展程序或属性时可显示的说明 |
IOException |
发生I/O错误时引发的异常 |
MemoryStream |
创建其支持存储区为内存的流 |
Path |
对包含文件或目录路径信息的String实例执行操作。这些操作是以跨平台的方式执行的 |
PathTooLongException |
当路径名或文件名超过系统定义的最大长度时引发的异常 |
RenamedEventArgs |
为Renamed事件提供数据 |
Stream |
提供字节序列的一般视图 |
续上表
类 名 |
说 明 |
StreamReader |
实现一个TextReader,使其以一种特定的编码从字节流中读取字符 |
StreamWriter |
实现一个TextWriter,使其以一种特定的编码向流中写入字符 |
StringReader |
实现从字符串进行读取的TextReader |
StringWriter |
实现一个用于将信息写入字符串的TextWriter。该信息存储在基础StringBuilder中 |
TextReader |
表示可读取连续字符系列的读取器 |
TextWriter |
表示可以编写一个有序字符系列的编写器。该类为抽象类 |
UnmanagedMemoryStream |
提供从托管代码访问非托管内存块的能力 |
可以看到,System.IO命名空间下的类提供了非常强大的功能。熟练掌握这些类可以编写出功能十分强大的代码。但对于初学者来说,常用的类有File、Directory、Path、FileInfo、DirectoryInfo、FileStream、StreamReader、StreamWriter、FileSystemWatcher等,这些类的功能可以满足一般应用程序的需求。下面的章节中,将对这些常用类进行逐一介绍。本章代码如无特别说明,都需添加对System.IO命名空间的引用,即:
using System.IO;
File类是本章中最重要和最基础的一个类。这个类里提供了42种公开方法,其中大部分方法为静态方法。File类提供了用于创建、复制、删除、移动和打开文件的静态方法,并协助创建FileStream对象。下面介绍的实例演示File类的用法。
创建一个Windows控制台应用程序,演示如何使用File类创建文件。
(1)创建一个名为FileCreate的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
//设置所要创建文件的绝对路径
string path = @"c:\file.txt";
//以路径为参数创建文件
File.Create(path);
}
按Ctrl+F5组合键运行程序,查看C盘根目录,如图9-1所示。
图9-1 运行结果
代码中变量path给出了文件的路径,利用File类的Create方法创建了该文件。
Windows的文件管理方式采用的是一种树形管理模式,文件的上层通常还存在若干层文件夹。本小节主要介绍文件夹类的知识。Directory类同File类相似,公开了用于创建、移动目录和子目录等静态方法。下面介绍一个实例,演示创建文件夹的方法。
创建一个Windows控制台应用程序,演示如何使用Directory类创建文件夹。
(1)创建一个名为DirCreate的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
//设置所要创建文件夹的绝对路径
string path = @"c:\Files";
//以路径为参数创建文件夹
Directory.CreateDirectory(path);
}
按Ctrl+F5组合键运行程序,查看C盘根目录,如图9-2所示。
图9-2 运行结果
代码中变量path给出了文件夹的路径,利用Directory类的Create方法创建了该文件夹。
文件信息类FileInfo与File类不同,它虽然也提供了创建、复制、删除、移动和打开文件的方法,并且帮助创建FileStream对象,但是它提供的仅仅是实例方法。因此要使用FileInfo类,必须先实例化一个FileInfo对象。FileInfo类的常用方法与File类基本相同。下面介绍一个实例,演示文件信息类的用法。
创建一个Windows控制台应用程序,演示如何使用FileInfo类。
(1)创建一个名为UseFileInfo的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
//设置所要检测文件的绝对路径
string m_path = @"c:\file.txt";
//以路径为参数构造FileInfo对象
FileInfo m_FileInfo = new FileInfo(m_path);
//检测文件是否存在
if (m_FileInfo.Exists)
{
Console.WriteLine("文件存在!");
}
else
{
Console.WriteLine("文件不存在!");
}
}
按Ctrl+F5组合键运行程序,运行结果如图9-3所示。
图9-3 运行结果
代码中首先给出了文件的路径,利用FileInfo类的Exist属性检查该文件是否存在。
文件夹信息类DirectoryInfo与文件信息类FileInfo相似,它是一个实例类,同样提供了Directory类中的大部分方法。同FileInfo类一样,使用DirectoryInfo类之前必须实例化一个DirectoryInfo对象。DirectoryInfo类拥有和FileInfo类几乎相同的属性。
创建一个Windows控制台应用程序,演示如何使用DirectoryInfo类。
(1)创建一个名为UseDirInfo的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
//设置所要检测文件夹的绝对路径
string m_path = @"c:\files";
//以路径为参数构造DirectoryInfo对象
DirectoryInfo m_DirInfo = new DirectoryInfo(m_path);
//检测文件夹是否存在
if (m_DirInfo.Exists)
{
Console.WriteLine("文件夹存在!");
}
else
{
Console.WriteLine("文件夹不存在!");
}
}
按Ctrl+F5组合键运行程序,运行结果如图9-4所示。
图9-4 运行结果
代码中首先给出了文件夹的路径,利用Exist属性检查该文件是否存在。
与文件类File和文件夹类Directory相比,文件信息类FileInfo和文件夹信息类DirectoryInfo具有其大部分功能。在实际应用中,读者应当注意选择使用不同的实现。
File类和Directory类适合于在对象上单一的方法调用。此种情况下静态方法的调用在速度上效率比较高,因为此种方法省去了实例化新对象的过程。
FileInfo类和DirectoryInfo类适合于对同一文件,或文件夹进行几种操作的情况。此种情况下实例化的对象不需每次都寻找文件,只需调用该实例化的方法,比较节省时间。