4. 使用流

现在,处理文件有更强大的选项:流。流的概念已经存在很长时间了。流是一个用于传输数据的对象,数据可以向两个方向传输:

  • 如果数据从外部源传输到程序中,这就是读取流。
  • 如果数据从程序传输到外部源中,这就是写入流。

外部源常常是一个文件,但也不完全都是文件。它还可能是:

  • 使用一些网络协议读写网络上的数据,其目的是选择数据,或从另一个计算机上发送数据。
  • 读写到命名管道上
  • 把数据读写到一个内存区域上。

一些流只允许写入,一些流只允许读取,一些流允许随机存取。随机存取允许在流中随机定位游标,例如,从流的开头开始读取,以后移动到流的末尾,再从流的一个中间位置继续读取。

在这些示例中,微软公司提供了一个.NET类System.IO.MemoryStream对象来读写内存,而System.Net.Sockets.NetworkStream对象处理网络数据。Stream类对外部数据源不做任何假定,外部数据源可以是文件流、内存流、网络流或任意数据源。

一些流也可以链接起来。例如,可以使用DeflateStream压缩数据。这个流可以写入FileStream、MemoryStream或NetworkStream。CryptoStream可以加密数据。也可以链接DeflateStream和CryptoStream,在写入FileStream。

使用流时,外部源甚至可以是代码中的一个变量。这听起来很荒缪,但使用流在变量之间传输数据的技术是一个非常有用的技巧,可以在数据类型之间转换数据。C语言使用类似的函数sprintf()在整型和字符串之间转换数据类型,或者格式化字符串。

使用一个独立的对象来传输数据,比使用FileInfo或DirectoryInfo类更好,因为把传输数据的概念与特定数据源分离开来,可以更容易交换数据源。流对象本身包含许多通用代码,可以在外部数据源和代码中的变量之间移动数据,把这些代码与特定数据源的概念分离开来,就更容易实现不同环境下代码的重用。

虽然直接读写流不是那么容易,但可以使用阅读器和写入器。这时另一个关于点分离。 阅读器和写入器可以读写流。例如,StringReader和StringWriter类,与本章后面用于读写文本文件的两个类StreamReader和StreamWriter一样,都是同一继承树的一部分,这些类几乎一定在后台共享许多代码。在System.IO名称空间中,与流相关的类的层次结构如下图所示。

对于文件的读写,最常用的类如下:

  • FileStream(文件流)——这个类主要用于在二进制文件中读写二进制数据。
  • StreamReader(流读取器)和StreamWriter(流写入器)——这两个类专门用于读写文本格式的流产品API。
  • BinaryReader和BinaryWriter——这两个类专门用于读写二进制格式的流产品API。

使用这些类和直接使用底层的流对象之间的区别是,基本流是按照字节来工作的。例如,在保存某个文档时,需要把类型为long的变量的内容写入一个二进制文件中,每个long型变量都占用8个字节,如果使用一般的二进制流,就必须显示地写入内存的8个字节中。

在C#代码中,必须执行一些按位操作,从long值中提取这8个字节。使用BinaryWriter实例,可以把整个操作封装在BinaryWriter.Write()方法的一个重载方法中,该方法的参数是long型,它把8个字节写入流中(如果流指向一个文件,就写入该文件)。对象的BinaryReader.Reader()方法则从流中提取8个字节,恢复long的值。

1. 使用文件流

下面对流进行编程,以读写文件。FileStream实例用于读写文件中的数据。要构造FileStream实例,需要以下4条信息:

  • 要访问的文件。
  • 表示如何打开文件的模式——例如,新建一个文件或打开一个现有的文件。如果打开一个现有的文件,写入操作是覆盖文件原来的内容,还是追加到文件的末尾?
  • 表示访问文件的方式——是只读、只写还是读写?
  • 共享访问——表示是否独占访问文件。如果允许其他流同时访问文件,则这些流是只读、只写还是读写文件?

第一条信息通常用一个包含文件的完整路径名的字符串来表示,本章只考虑需要该字符串的那些构造函数。除了这些构造函数外,一些其他的构造函数用本地Wndows句柄来处理文件。其余3条信息分别由3个.NET枚举FileMode、FileAccess和FileShare来表示,这些枚举的值很容易理解,如下表所示。

注意,对于FileMode,如果要求的模式与文件的现有状态不一致,就会抛出一个异常。如果文件不存在,Append、Open和Truncate就会抛出一个异常;如果文件存在,CreateNew就会抛出一个异常。Create和OpenOrCreate可以处理这两种情况,但Create会删除任何现有的文件,新建一个空文件。因为FileAccess和FileShare枚举是按位标志,所以这些值可以与C#的按位OR运算符"|"合并使用。

(1). 创建FileStream

StreamSamples的示例代码使用如下名称空间:

System

System.Collectoins.Generic

System.Globalization

System.IO

System.Linq

System.Text

System.Threading.Tasks

FileStream有很多构造函数。下面的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值