26.2 流

流(Stream)是字节序列的抽象概念,例如文件、输入/输出设备、内部进程通信管道或者TCP/IP套接字。Stream是所有流的抽象基类,每种具体的存储介质都可以通过Stream的派生类来实现。Stream及其派生类提供这些不同类型的输入和输出的一般视图,使开发者不必了解操作系统和基础设备的具体细节。

流涉及以下三个基本操作:

❑可以读取流。读取是从流到数据结构(如字节数组)的数据传输;

❑可以写入流。写入是从数据结构到流的数据传输;

❑流可以支持查找。查找是对流内的当前位置进行的查询和修改。查找功能取决于流具有的后备存储区类型。例如,网络流没有当前位置的统一概念,因此一般不支持查找。Stream类的一些主要成员如表26-2所示。

26.2 流 - 图1

上述成员大体分三种:抽象成员、虚成员和一般成员。其中,抽象成员又分为抽象属性和抽象方法,虚成员为虚方法。所有的抽象成员都要求必须在派生类中实现,而虚成员则可以根据派生类自己的情况选择是否实现(覆写)。

也有一些派生类,因为必须实现某些抽象方法或抽象属性,但又无法支持这些方法或属性,因此在实现时简单地抛出异常以指示调用类,此类成员不被支持。例如NetworkStream类的Length属性和Seek方法,它们的实现如代码清单26-4和代码清单26-5所示。

代码清单26-4 NetworkStream类中对Length属性的实现


public override long Length

{

get

{

throw new NotSupportedException(SR.GetString("net_noseek"));

}

}


代码清单26-5 NetworkStream类中对Seek方法的实现


public override long Seek(long offset,SeekOrigin origin)

{

throw new NotSupportedException(SR.GetString("net_noseek"));

}


Stream类主要的派生关系如图26-2所示。

26.2 流 - 图2

图 26-2 Stream及其主要派生类

这些派生类简单说明如下:

❑FileStream。FileStream类是从Stream类继承而来的实体类,它用于将数据以流的形式写入或读出文件。

❑MemoryStream。MemoryStream类是一个实体类,它从Stream类继承而来,用于在内存中写入和读出数据。

❑BufferedStream。BufferedStream类是从Stream类继承而来的实体类,它用于向另一种类型的流提供额外的内存缓冲区。

❑DeflateStream。Deflate Stream类中提供了使用Deflate算法压缩和解压缩流的方法。Deflate算法是无损文件压缩和解压缩的行业标准算法。无损文件压缩允许从压缩的数据重新构造准确的数据。不能使用DeflateStream类来压缩大于4 GB的文件。

❑GzipStream。如果要在压缩过程中检查错误或要与其他操作系统所用程序共享压缩数据,则要使用GZipStream类。GZipStream类包含使用GZip数据格式进行压缩和解压缩文件的方法。使用GZipStream格式压缩的文件以gz扩展名保存。其他操作系统经常使用GZip格式,该类不能用于解压缩大于4GB的文件。

❑NetworkStream。提供在阻止模式下通过Stream套接字发送和接收数据的方法。

System.IO命名空间中提供了不同的读写器来对流中的数据进行操作,这些类通常成对出现,一个用于读,另一个用于写,不同类型的读写器分别处理文本、流、字符串和二进制数据。这些读写器如下:

❑文本数据和字符串读写器。它们是抽象基类,无法直接实例化。

 ■TextReader类

 ■TextWriter类

❑字符串读写器

 ■StringReader类

 ■StringWriter类

❑二进制数据读写器

 ■BinaryReader类

 ■BinaryWriter类

❑流读写器

 ■StreamReader类

 ■StreamWriter类

这些读写器之间的关系并非孤立的,它们之间的关系如图26-3所示。需要注意的是,TextReader和TextWriter定义了如何以文本(而不是字节)形式对流进行读写,TextReader和TextWriter都是抽象类,它们各有两个派生类:StreamReader、StringReader和StreamWriter、StringWriter。

26.2 流 - 图3

图 26-3 读写器的继承结构

我们以StreamReader和StreamWriter为例学习读写器的使用方法,如下所示。


using System;

using System.IO;

namespace ProgrammingCSharp4

{

class IOSample

{

public static void Main(string[]args)

{

//要操作的文件名

string file="demo.txt";

FileStream fs=new FileStream(file,FileMode.Create);

TextWriter writer=new StreamWriter(fs);

writer.WriteLine(“C#4.0权威指南”);

writer.Close();

fs.Close();

fs=new FileStream(file,FileMode.Open);

TextReader reader=new StreamReader(fs);

Console.WriteLine(reader.ReadToEnd());

reader.Close();

fs.Close();

}

}

}