《ASP.NET3.5网站开发从入门到精通》第9章文件操作的利器——C#文件流文件和流的概念和FileStream类读写文 本文件读写二进制文件读写内存流File类和Directory类第9章文件操作的利器——C#文件流文件和 流的概念和FileStream类读写文本文件读写二进制文件读写内存流File类和Directory类9. 1操作文件的流模型--文件和流文件流像自来水管道中的水流一样,让我们通过无形的管道来对磁盘文件进行操作,本章重点介绍如何利用 C#文件流来操作磁盘文件。9.1.1文件和流的概念C#中流的概念可以和生活中的“流”相对应。在生活中有水流、电流等,首先要 有一个源头,还需要有传输的管道,水流有河床、水管等作为传输管道,电流有电线,而这些“流”都会有一个目的地,就是它的流向。C#中的流 也需要有源头——文件,还需要有数据流入流出的管道以及数据的流向。C#采用流模型读写文件里的数据,按照流的方向把流分为两种:输入流 和输出流。输入流用于将数据读到程序可以访问的内存或变量中。输入流可以来自任何源,在此我们主要分析读取磁盘文件,可以理解为以文件为源 ,以内存为目的地。输出流用于向某些外部目标写入数据,可以是磁盘文件、打印设备或另一个程序。在此我们主要关注以内存为源,文件为目的地 的输出流。流是二进制字节序列的面向对象的抽象概念,.NET中用流进行输入输出操作。文件从广义上可看成是保存在磁盘上的二进制字节, 是按一定格式存储的信息,能用流对文件进行操作,如:读取文件内容、将信息写入文件等。Stream类是所有流类的抽象基类,它提供了流 的基本功能。流是字节序列的抽象概念,如文件、输入/输出设备、内部进程通信管道或者TCP/IP套接字都可以看作流。流涉及以下三个 基本操作。⑴从流读取:读取是从流到数据结构(如字节数组)的数据传输。⑵向流写入:写入是从数据结构到流的数据传输。⑶支持 查找:查找是对流内的当前位置进行查询和修改。System.IO命名空间的类大致可分为以下三组。⑴操作流的类:包括文件流、内存 流,以及读写这些流的类⑵操作目录的类:包括对文件夹目录进行创建、移动、删除等操作,以及对磁盘信息进行访问的类。⑶操作文件的 类:包括对文件进行创建、移动、删除等操作,以及获取文件信息等比较常用的类有:FileStream类、StreamReader类、 StreamWriter类、BinaryReader类、BinaryWriter类、MemoryStream类、File类、Fil eInfo类、Directory类和DirectoryInfo类等,下面小节将对这些比较常用的类逐一介绍。9.1.2File Stream类FileStream称为文件流,用于读取和写入文件,FileStream类的实例实际上代表一个磁盘文件。FileS tream类继承于Stream类。下表列出了FileStream类的常见的成员及其说明。下面对FileStream类成员中比 较重要的进行详细介绍。⑴Position属性。获取或设置此流的当前位置。属性值:此流的当前位置。⑵Close()方法。在创 建和使用完一个流后一定要将其及时关闭。⑶Flush()方法。在调用Close()方法之前调用Flush()方法,可以将以前写入 缓冲区的任何数据都复制到文件中,并且缓冲区被清除。⑷Seek()方法。使用代码如下。01aFile.Seek(8,S eekOrigin.Begin)构造FileStream类对象时的文件打开方式,如下表。FileMode.Append 如果 文件存在则打开,并把读写位置定位到文件末尾。如果文件不存在则创建新文件。这种方式只能和FileAccess.Write访问方式一起 使用。 FileMode.Create 创建一个新文件。如果文件存在。则覆盖原有文件。FileMode.CreateNew 创 建一个新文件,如果文件存在则出现异常。 FileMode.Open 打开一个已有文件。FileMode.OpenOrCreat e 打开一个已有文件,如果文件不存在,则创建一个新文件。 FileMode.Truncate 打开一个已有文件。然后把文件的长度 置为0。 构造FileStream流对象时的文件访问方式。FileAccess.Read 对文件进行读访问,只能从文件中读数据。 FileAccess.ReadWrite 对文件进行读写访问。FileAccess.Write 对文件进行写访问,只能向文件中 写入数据。下面的代码是打开一个现有文件并将信息显示到文本框中01openFileDialog1.Filter=" 文本文件(.txt)|.txt"; //打开文件对话框的筛选器02openFileDialog1.ShowDialo g(); //显示打开文件对话框03textBox1.Text=openFileDialog1.FileName; //在文本框中显示打开文件的文件名04FileStreamfs=File.OpenRead(textBox1.Te xt); //创建FileStream实例对象05byte[]b=newbyte[1024]; //创建字节数组 b06while(fs.Read(b,0,b.Length)>0) //循环读文件内容到缓冲区b中07 {08textBox2.Text=Encoding.Default.GetString(b); //将字节数组中的字节解码为字符串09}第9章文件操作的利器——C#文件流文件和流的概念和Fi leStream类读写文本文件读写二进制文件读写内存流File类和Directory类9.2读写文本文 件除了使用FileStream类读写文本文件,.NET还提供了StreamWriter类和StreamReader类专门处理文本 文件,这两个类从底层封装了文件流,读写时不需要重新进行编码。9.2.1StreamReader类StreamReader类 可以读取标准文本文件的各行信息。StreamReader类的构造函数有多个重载,下面列出比较常用的两种方式演示如何创建一个Stre amReader类的实例:01//指定文件路径作为参数02stringstrFilePath=@"c:\t est.txt";03StreamReaderReader=newStreamReader(strFilePath );04//指定文件路径和编码作为参数05stringstrFilePath=@"c:\test.txt"; 06StreamReaderReader=newStreamReader(strFilePath,Encodin g.Default);下表列出了StreamReader类常用的方法及其说明。成员名称 类别 说明 Close 方法 关闭 StreamReader对象和基础流,并释放与读取器关联的所有系统资源Equals 方法 确定两个Object实例是否相等 Read 方法 读取输入字符串中的下一个字符或下一组字符 ReadLine 方法 从基础字符中读取一行 ToString 方法 返回表示当前Object的String 下面对StreamReader类中比较重要的方法进行详细介绍。⑴Close ()方法。在创建和使用完一个StreamReader后一定要将其及时关闭。⑵ReadLine()方法。返回值为输入流中的下一行 ;如果到达了输入流的末尾,则为空引用。9.2.2StreamWriter类StreamWriter类可以把数据写入文本文件 ,如果指定的文件不存在,可以先创建一个新文件。StreamWriter类的构造函数有多个重载,下面列出比较常用的两种方式演示如何创 建一个StreamWriter类的实例:01//指定文件路径作为参数02stringstrFilePath= @"c:\test.txt";03StreamWriterWriter=newStreamWriter(strF ilePath);04//指定文件路径和Boolean作为参数05stringstrFilePath=@"c :\test.txt";06StreamWriterWriter=newStreamWriter(strFileP ath,true);下表列出了StreamWriter的常用成员及其说明:成员名称 类别 说明 Close 方法关闭StreamWriter对象和基础流 Equals 方法 确定两个Object实例是否相等 Write 方法 写入到StringWriter的实例中 WriteLine 方法 写入重载参数指定的某些数据,后跟行结束符 ToString 方法 返回表示当前Object的String下面对StreamWriter类中比较重要的方法进行详细介绍。 ⑴Close()方法。在创建和使用完一个StreamWriter后一定要将其及时关闭。⑵WriteLine()方法。返回值: 默认行结束符是(“\r\n”),但使用NewLine属性可以更改此值。WriteLine()只用于字符串,并且会自动追加一个换行符 。Write()方法不追加换行符,可以向文本流写入字符串,也可以写任何基本数据类型(int32、Single等)的文本形式。【范 例9-1】使用StreamReader和StreamWriter类读写文本文件第9章文件操作的利器——C#文件流文件 和流的概念和FileStream类读写文本文件读写二进制文件读写内存流File类和Directory类9 .3读写二进制文件对文件进行操作的常见模式有两种:文本模式和二进制模式。前面给大家介绍了如何读写文本文件,下面我们再给大家介 绍如何读写二进制文件。读写二进制文件的类主要有BinaryWriter和BinaryReader类。9.3.1BinaryR eader类BinaryReader类执行对当前输入流进行指定字节数的二进制读取,其读数据的方法很多。BinaryReader类 创建对象时必须基于所提供的流文件。下表列出了BinaryReader类常用的成员及其说明。成员名称 类别 说明 Read 方法 从指定流读取字符,并将指针迁移,指向下一个字符ReadByte() 方法 从指定流读取一个字节值,并将在流中的位置向前移一个字 节ReadInt16() 方法 从指定流读取两个字节带符号的整数值,并将在流中的位置向前移两个字节 ReadInt32() 方法 从指定流读取四个字节带符号的整数值,并将在流中的位置向前移4个字节 ReadString() 方法 从指定流读取字符串,该 字符串的前缀为字符串长度,编码为整数,每次7比特 ReadDecimal() 方法 从指定流读取一个十进制数值,并将在流中的位置 向前移动16个字节 9.3.2BinaryWriter类BinaryWriter类以二进制形式将基元类型写入流,并支持用 特定的编码写入字符串。它提供的一些方法和BinaryReader是对称的。下表列出了BinaryWriter类的常用成员及其说明 :成员名称 类别 说明 Write 方法 将值写入流,有很多重载,适用于不同的数据类型 Flush() 方法 清楚缓存区 Close() 方法 关闭当前流 【范例9-2】利用BinaryReader和BinaryWriter读写二进制文件第 9章文件操作的利器——C#文件流文件和流的概念和FileStream类读写文本文件读写二进制文件读写内存流 File类和Directory类9.4读写内存流前面介绍了文件流类FileStream,除文件流之外还存在多种流,例 如:网络流、内存流、缓存流等。本节我们来介绍读写内存流。9.4.1读写内存MemoryStream称为内存流,是内存本身的 抽象概念,必须注意它是内存而不是以磁盘或网络连接作为基础的存储区。MemoryStream封装以无符号字节数组形式存储的数据,该 数组在创建MemoryStream对象时被初始化,或者该数组可创建为空数组。可在内存中直接访问这些封装的数据。内存流可降低应用 程序中对临时缓冲区和临时文件的需要,在程序设计中有一定的应用。FileStream对象的数据来自文件,而MemoryStream对 象的数据来自内存缓冲区。这两个类都继承自Stream类。9.4.2读写缓冲区BufferdeStream称为内存缓冲区流, 是内存中缓冲区的抽象,它可以读取或写入另一个流。缓冲区是内存中的字节快,用于缓存数据,从而减少对操作系统的调用次数。因此,缓冲区可 提高程序读取和写入数据的性能。虽然使用缓冲区可进行读取和写入,但不能同时进行这两个操作。BufferedStream经常和其他类型 的流联合使用。下面我们举个例子来说明MemoryStream类的用法。。【范例9-3】内存流示例测试字符串第9章 文件操作的利器——C#文件流文件和流的概念和FileStream类读写文本文件读写二进制文件读写内存流F ile类和Directory类9.5文件和文件夹操作在我们进行程序设计时,接触最多的就是和文件打交道,为了便于对文件和目 录进行操作(包括创建,复制,删除,移动和打开文件或目录),.Net提供了文件和目录类。9.5.1File类和FileInfo 类File类和FileInfo类用来管理文件。这两个类的功能类似,区别在于File类是一个静态的类,不能实例化,可以使用该类的静 态方法管理文件。而FileInfo类需要实例化后,再使用FileInfo对象的实例方法管理文件。因此如果用户打算多次重用某个对象, 可考虑使用FileInfo的实例方法,而不是File类的相应静态方法,因为FileInfo的实例方法并不总是需要进行安全检查。默认 情况下,该类将向所有用户授予对新文件的完全读/写访问权限。下表列出了File类的常用成员及其说明成员名称 类别 说明 Cop y 方法 将现有文件复制到新文件 reate 方法 在指定路径中创建文件 Delete 方法 删除指定的文件。如果指定文件不存 在,则不引发异常 Move 方法 将制定文件移到新位置,并提供指定新文件名的选项 Open 方法 打开指定路径上的FileSt ream 下面对File类中比较重要的方法进行详细介绍。⑴Copy()方法。参数sourceFileName指要复制的文件名 称;参数destFileName指目标文件的名称,它不能使一个目录或现有文件。⑵Create()方法。返回值为一个FileSt ream,它提供对参数path中指定的文件的读/写访问。⑶Open()方法。参数path指要打开的文件;mode指Filemo de值,用于指定在文件不存在时是否创建该文件,并确定是保留还是改写现有文件的内容。返回值指以指定模式打开的制定路径上的FileSt ream,具有读/写访问权限并且不共享。下面代码演示了如何利用File类的方法来复制、移动、删除文件。01const stringSourceFilePath=@"C:\FileDemo1.txt"; //定义常量表示源文件路径02 conststringDestFilePath=@"C:\FileDemoCopy1.txt"; //定义常量表示目标文件路 径03if(!File.Exists(SourceFilePath)) //如果文件FileDemo1.txt存在则 执行下面代码04{05File.WriteAllText(SourceFilePath ,"这是一个示范文件的复制,移动,删除的例子");06}07Console.WriteLine ("文件的复制操作");08File.Copy(SourceFilePath,DestFilePath,tru e); //复制文件09Console.WriteLine("文件的删除操作");10File.D elete(DestFilePath); //删除文件11Console.WriteLine("文件的移动操作") ;12File.Move(SourceFilePath,DestFilePath) //移到文件下面代码演示了 如何使用FileInfo类的方法复制、移动、删除文件01conststringsourceFilePath=@"C :\FileInfoDemo.txt";//定义常量表示源文件路径02conststringdestFilePath =@"C:\FileInfoDemo2.txt";//定义常量表示目标文件路径03//使用构造函数构造FileInfo类 的实例,需要传递一个文件路径的字符串值04FileInfofi=newFileInfo(sourceFilePa th); //定义FileInfo对象fl05//Exists现在是FileInfo类的属性06if(!fi .Exists) //如果源文件不存在执行如下代码07{08//调用fi.CreateText方法创建文 本文件09using(StreamWritersw=fi.CreateText())10{ 11sw.WriteLine("这是使用FileInfo方法创建的文本文件");//写入缓存12 sw.Flush(); //刷新流将缓存中的内容写入磁盘文件路径13}14}151 61718File.Delete(destFilePath); //调用实例方法Delete删除文件 19fi.CopyTo(destFilePath); //调用实例方法CopyTo复制文件2021F ile.Delete(destFilePath); //调用实例方法Delete删除文件22fi.MoveTo(dest FilePath); //调用实例方法MoveTo移动文件2324using(StreamWritersw =fi.AppendText()) //使用实例方法AppendText追加文本25{26 sw.WriteLine("这是追加的文件本");27sw.Flush();28}29 30using(StreamReadersr=fi.OpenText()) //使用OpenText方法打开文本文 本31{32Console.WriteLine(sr.ReadToEnd());33 }34Console.ReadLine();FileInfo类和File类之间许多调用方法都是相同的。我 们只对FileInfo类中比较重要的属性进行介绍。⑴DirectoryName属性。获取表示目录的完整路径的字符串。属性值:表 示目录的完整路径的字符串。⑵Extension属性。获取表示文件扩展名部分的字符串。属性值:包含FileSystemInfo扩 展名的字符串。⑶Length属性。获取当前文件的大小。属性值:当前文件的大小。9.5.2Directory类和Direc toryInfo类Directory类和DirectoryInfo类用来管理目录。使用这两个类可以完成对目录及其子目录的创建、 赋值、删除、移动和打开文件的实例方法。通过对这两个类的使用,开发人员就可以获得稳健的相关信息,甚至还可以定义隐藏目录和只读目录。 Directory类的所有方法都为静态方法,因此无需创建对象即可调用,这些方法可以操纵和查询任何目录的信息。而DirectoryI nfo类需要实例化才可以调用其方法,从而有效地对一个目录进行多种操作。下表列出了Directory类的常用成员及其说明成员名 称 类别 说明 CreateDirectory 方法 创建指定路径中的所有目录和子目录,并返回一DirectoryInfo对象。 Delete 方法 删除指定目录 Exists 方法 判断指定目录是否存在。返回Boolean值。SetCurrentDirectory 方法 设置系统的当前目录。 GetCurrentDirectory 方法 取得系统的当前目录。 GetDirectoryRoot 方法 取得指定目录的根目录。GetFiles 方法 返回指定目录下的所有文件或者指定条件的文件。 GetLigicalDrives 方法 取得所有驱动器的名称 GetParent 方法 取得指定目录的父目录: Move 方法 移动指定目录 下面对Directory类常用的方法详细介绍。⑴CreateDirectory()方法。参数path指定要创建的目录路径。返回值:由path指定的DirectoryInfo。⑵Dleete()方法。从指定目录删除空目录。参数path指定要移除的空目录的名称,此目录必须为可写或为空。⑶GetFIles()方法。返回值:指定目录中文件名的String数组。DirectoryInfo类和Directory类之间的关系与FileInfo类和File类之间之间的关系十分类似,这里就不再赘述。下面我们举个例子来说明Directory类的常用属性和方法。【范例9-4】输出程序目录信息。9.6练一练9.7跟我上机在C#中编写一个Windows应用程序,实现以下功能:删除文件夹下所有内容。 |
|