System.IO命名空间包含允许在数据流和文件上进行同步和异步读取及写入的类型。这里需要注意文件和流的差异,文件是一些具有永久存储及特定顺序的字节组成的一个有序的、具有名称的集合。流是提供一种向后备存储写入字节和从后备存储读取字节的方式。
System.IO命名空间中的一些类及说明:
| 类 | 说明 |
|---|---|
| File | 静态实用类,提供许多静态方法,用于移动、复制和删除文件 |
| Directory | 静态实用类,提供许多静态方法,用于移动、复制和删除目录 |
| Path | 实用类,用于处理路径名称 |
| FileInfo | 表示磁盘上的物理文件,该类包含处理此文件的方法。要完成对文件的读写工作,就必须创建Stream对象。 |
| DirectoryInfo | 表示磁盘上的物理目录,该类包含处理此目录的方法。 |
| FileSystemInfo | 用作FileInfo和DirectoryInfo的基类,可以使用多态性同时处理文件和目录。 |
| FileStream | 表示可写或可读,或二者均可的文件。可以同步或异步地读写文件。 |
| StreamReader | 从流中读取字符数据,可以使用FileStream作为基类创建。 |
| StreamWriter | 向流写入字符数据,可以使用FileStream作为基类创建 |
| FileSystemWatcher | 用于监控文件和目录,提供了这些文件和目录发生变化时应用程序可以捕获的事件。 |
File类和Directory类分别用来对文件和各种目录进行操作,这两个类可以被实例化,但不能被其它类继承。
File类和Directory类就好比一个工厂,文件和文件夹就好比工厂所制作的产品,而工厂和产品的关系主要表现在以下几个方面:工厂可以自行开发产品(文件和文件夹的创建),也可以对该产品进行批量生产(文件和文件夹的复制,将产品进行销售(文件和文件夹的移动)以及将有质量问题的产品进行回收消除(文件和文件夹删除)。
File类支持对文件的基本操作,它包括用于创建、复制、删除、移动和打开文件的静态方法,并协助创建FileStream对象。
| 方法 | 说明 |
|---|---|
| Copy() | 将文件从源位置复制到目标位置 |
| Create() | 在指定的路径上创建文件 |
| Delete() | 删除文件 |
| Open() | 返回指定路径上的FileStream对象 |
| Move() | 将指定的文件移到新位置。可在新位置为文件指定不同名称 |
| Exists() | 确定指定的文件是否存在 |
| Replace | 使用其他文件的内容替换指定文件的内容,这一过程将删除原始文件,并创建被替换文件的备份 |
说明:
Directory类公开了用于创建、移动、枚举、删除目录和子目录的静态方法。
| 方法 | 说明 |
|---|---|
| CreateDirectory() | 创建具有指定路径的目录 |
| Delete() | 删除指定的目录及其中的所有文件 |
| GetDirectories() | 返回表示指定目录下的目录名的string对象数组 |
| EnumerateDirectories | 与GetDirectories()类似,但返回目录名的IEnumerable集合 |
| GetFiles() | 返回在指定目录中的文件名的string对象数组 |
| EnumerateFiles() | 与GetFiles()类似,但返回文件名的IEnumerable集合 |
| GetFilesSystemEntries() | 返回指定目录中的文件和目录名的string对象数组 |
| EnumerateFileSystemEntries() | 与GetFilesSystemEntries()类似,但返回文件和目录名的IEnumerable集合 |
| Move() | 将指定目录移到新位置。可在新位置为文件夹指定一个新名称 |
使用FileInfo和DirectoryInfo类可以方便地对文件和文件夹进行操作
FileInfo类和File类之间许多方法调用都是相同的,但是FileInfo类没有静态方法,该类中的方法仅可以用于实例化的对象。File类是静态类,所以他的调用需要字符串参数为每一个方法调用规定文件的位置。因此如果要在对象上进行单一方法调用,则可以使用静态File类。
FileInfo对象表示磁盘或网络位置上的文件。提供文件路径,就可以创建一个FileInfo对象。
FileInfo fi = new FileInfo(@"F:\Log.txt");
FileInfo类的常用属性及说明:
| 属性 | 说明 |
|---|---|
| CreationTime | 获取或设置当前FileSystemInfo对象的创建时间 |
| Directory | 获取父目录的实例 |
| DirectoryName | 获取表示目录的完整路径的字符串 |
| Exist | 获取指定文件是否存在的值 |
| Extension | 获取表示文件扩展名部分的字符串 |
| FullName | 获取目录或文件的完整目录 |
| IsReadOnly | 获取或设置确定当前文件是否只读的值 |
| LastAccessTime | 获取或设置上次访问当前文件或目录的时间 |
| LastWriteTime | 获取或设置上次写入当前文件或目录的时间 |
| length | 获取当前文件的大小 |
| Name | 获取文件名 |
DirectoryInfo类的作用类似于FileInfo类。它是一个实例化的对象,表示计算机上的单一目录。
DirectoryInfo类的大多数属性继承自FileSystemInfo,与FileInfo类一样,但这些属性作用于目录上,而不是文件上。还有两个DirectoryInfo专用属性。
| 属性 | 说明 |
|---|---|
| parent | 检索一个DirectoryInfo对象,表示包含当前目录的目录。这个属性是只读的 |
| Root | 检索一个DirectoryInfo对象,表示包含当前目录的跟目录。这个属性是只读的。 |
通过File.ReadAllText和File.WriteAllText,引入了一种使用字符串读写文件的方法。除了使用一个字符串之外,还可以给文件的每一行使用一个字符串。
为了访问文件和目录,需要定义文件和目录的名称,包括父文件夹。使用字符串连接操作符合并多个文件夹和文件时,很容易遗漏单个分隔符或使用太多的字符串。为此,Path类可以提供帮助,因为这个类会添加缺少的分隔符。
我们不能去实例化Path类,Path类提供了一些静态方法,可以更容易的对路径名执行操作。
例如:假定要显示文件夹D:\projects中ReadMe.txt文件的完整路径名,可以用下述代码查找文件的路径:
WriteLine(Path.Combine(@"D:\Projects","ReadMe.txt"));
Path.Combine()是这个类常用的一个方法,Path类还实现了其他方法,这些方法提供路径的信息,或者以要求的格式显示信息。
基类库提供了写入的方法:WriteAllText(FilePath,Contents)、WriteAllBytes()、WriteAllLines()。方法的具体内容与读取文件的方法类似。
写入的新内容不是添加到原有内容的后面,而是完全覆盖以前的内容。
在.NET Framework中进行的所有输入和输出工作都要用到流(stream)。流是序列化设备的抽象表示是一种数据的处理方式。序列化设备可以线性方式存储数据,并按照同样的方式访问:一次访问一个字节。
此设备可以是磁盘文件、网络通道、内存位置或其他支持一线性方式读写的对象。把设备变成抽象的,就可以隐藏流的底层目标和源。
数据小,可以直接一次性搬运。数据大,可以把数据当做水,接一个水管,一点一点搬运。
有两种类型的流:
Filestream类公开以文件为主的Stream,它表示在磁盘或网络路径上指向文件的流。一个FileStream类的实例实际上代表一个磁盘文件,它通过Seek方法进行对文件的随机访问,也同时包含了流的标准输入、标准输出、标注错误等。
FileStream默认对文件的打开方式是同步的,但它同样很好地支持异步操作。FileStream对象支持使用Seek方法对文件进行随机访问。Seek允许将读取/写入位置移动到文件中的任意位置。
| 属性 | 说明 |
|---|---|
| CanRead | 获取一个值,该值指示当前流是否支持读取 |
| CanSeek | 获取一个值,该值指示当前是否支持查找 |
| CanTimeout | 获取一个值,该值确定当前流是否可以超时 |
| CanWrite | 获取一个值,该值指示当前流是否支持写入 |
| IsAsync | 获取一个值,该值指示FileStream是异步还是同步打开的 |
| Length | 获取用字节表示的流长度 |
| Name | 获取传递给构造函数的FileStream的名称 |
| Position | 获取或设置此流的当前位置 |
| ReadTimeout | 获取或设置一个值,该值确定流在超时前尝试读取多长时间 |
| WriteTimeout | 获取或设置一个值,该值确定流在超时前尝试写入多长时间 |
| 方法 | 说明 |
|---|---|
| BeginRead | 开始异步读操作 |
| BeginWrite | 开始异步写操作 |
| Close | 关闭当前流并释放与之关联的所有资源 |
| EndRead | 等待挂起的异步读取完成 |
| EndWrite | 结束异步写入,在I/O操作完成之前一直阻止 |
| Lock | 允许读取访问的同时防止其他进程更改FileStream |
| Read | 从流中读取字节块并将该数据写入给定的缓冲区中 |
| ReadByte | 从文件中读取一个字节,并将读取位置提升一个字节 |
| Seek | 将该流的当前位置设置为给定值 |
| SetLength | 将该流的长度设置为给定值 |
| Unlock | 允许其他进程访问以前锁定的某个文件的全部或部分 |
| Write | 使用从缓冲区读取的数据将字节块写入该流 |
| WriteByte | 将一个字节写入文件流的当前位置 |
要用FileStream类操作文件就要先实例化一个FileStream对象,FileStream类的构造函数具有许多不同的重载形式,其中包括了一个最重要的参数,即FIleMode枚举。
| 枚举成员 | 文件存在 | 文件不存在 |
|---|---|---|
| Append | 打开文件,流指向文件的末尾处,只能与枚举FileAccess.Write结合使用 | 创建一个新文件。只能与枚举FileAccess.Write结合使用 |
| Create | 删除该文件,然后创建新文件 | 创建新文件 |
| CreateNew | 抛出异常 | 创建新文件 |
| Open | 打开文件,流指向文件开头处 | 抛出异常 |
| OpenOrCreate | 打开文件,流指向文件开头处 | 创建新文件 |
| Truncate | 开发文件,清除其内容。流指向文件开头处,保留文件的初始创建日期 | 抛出异常 |
对文件进行非FileAccess枚举成员指定的操作会导致抛出异常。此属性的作用是,基于用户的权限级别改变用户对文件的访问权限。
| 成员 | 说明 |
|---|---|
| Read | 打开文件,用于只读 |
| Write | 打开文件,用于只写 |
| ReadWrite | 打开文件,用于读写 |
单字节读取写入:ReadByte()、WriteByte()
using System;
using System.IO;
namespace FileStream_1
{
public class Class1
{
static void Main(string[] args)
{
FileStream readFileStream = new FileStream(@"E:\新建 XLSX 工作表.xlsx", FileMode.Open, FileAccess.Read);
FileStream writeFileStream = new FileStream(@"E:\why.xlsx", FileMode.Create, FileAccess.Write);
int nextByte = -1;
while ((nextByte=readFileStream.ReadByte())!= -1)
{
writeFileStream.WriteByte((byte)nextByte);
}
writeFileStream.Close();
readFileStream.Close();
}
}
}
字节块读取写入:Read()、Write();
using System;
using System.IO;
namespace FileStream_2
{
public class Class1
{
static void Main(string[] args)
{
DataTime before = DataTime.Now;
FileStream readFileStream = new FileStream(@"E:\新建 XLSX 工作表.xlsx", FileMode.Open, FileAccess.Read);
FileStream writeFileStream = new FileStream(@"E:\why.xlsx", FileMode.Create, FileAccess.Write);
byte[] buffer = new byte[1024];
int count = 0;
while ((count = readFileStream.Read(buffer, 0, 1024))!= 0)
{
writeFileStream.Write(buffer, 0, count);
}
writeFileStream.Close();
readFileStream.Close();
DataTime after = DataTime.Now;
TimeSpan ts = after.Subtract(before);
Console.WriteLine(ts.TotalMilliseconds);
}
}
}
我们对文本文件的读写一般使用StreamReader和StreamWriter,因为不同的文本有不同的编码格式,这个StreamReader会帮我们自动处理。
StreamReader是专门用来读取文本文件的类,它可以从底层Stream对象创建StreamReader对象的实例,而且也能指定编码规范参数。创建StreamReader对象后,它提供了许多用于读取和浏览字符数据的方法。
StreamReader类的常用方法及说明
| 方法 | 说明 |
|---|---|
| Close | 关闭StreamReader |
| Read | 读取输入字符串中的下一个字符或下一组字符 |
| ReadBlock | 从当前流中读取最大count的字符串并从index开始将该数据写入Buffer |
| ReadLine | 从基础字符串中读取一行 |
| ReadToEnd | 将整个流或从流的当前位置到流的结尾作为字符串读取 |
StreamReader sr = new StreamReader(@"c:\xx\ReadMe.txt");
StreamReader str = new StreamReader(@"c:\xx|xx.txt",Encoding.UTF8);
FileStream fs = new FileStream(@"c:\xx\xx.txt",FileMode.Open,FileAccess.Read,FileShare.None);
StreamReader sr = new StreamReader(fs);
FileInfo myFile = new FileInfo(@"c:\xx\xx.txt");
StreamReader sr = myFile.OpenText();
StreamWriter是专门用来处理文本文件的类,可以方便地向文本文件中写入字符串。同时也负责重要的转换和处理向FileStream对象写入工作。
StreamWriter类的常用属性及说明
| 属性 | 说明 |
|---|---|
| Encoding | 获取将输入写入到其中的Encoding |
| Formatprovider | 获取控制格式设置的对象 |
| NewLine | 获取或设置由当前TextWriter使用的行结束字符串 |
StreamWriter类的常用方法及说明
| 方法 | 说明 |
|---|---|
| Close | 关闭当前的StringWriter和基础流 |
| Write | 写入到StringWriter的此实例中 |
| WriteLine | 写入重载参数指定的某些数据,后跟行结束符 |
StreamWriter sr = new StreamWriter(@"c:\xx\ReadMe.txt");
StreamWriter str = new StreamWriter(@"c:\xx|xx.txt",Encoding.UTF8);
FileStream fs = new FileStream(@"c:\xx\xx.txt",FileMode.Open,FileAccess.Read,FileShare.None);
StreamWriter sr = new StreamWriter(fs);
FileInfo myFile = new FileInfo(@"c:\xx\xx.txt");
StreamWriter sr = myFile.OpenText();
using System;
using System.IO;
namespace StreamReader_Writer
{
public class Class1
{
static void Main(string[] args)
{
string sourceFile = @"E:\TextFile.txt";
string destinationFile = @"E:\why.txt";
StreamReader sr = new StreamReader(sourceFile);
StreamWriter sw = new StreamWriter(destinationFile);
string line = null;
while((line = sr.ReadLine())!= null)
{
sw.WriteLine(line);
}
sw.Close();
sr.Close();
}
}
}