首页 > 代码库 > 什么是流,.NET中有哪些常见的流

什么是流,.NET中有哪些常见的流

分析问题

  流是一种对于字节流的直接操作。例如在处理一个文件时,本质上需要通过操作系统提供的API来进行文件打开,读取文件中的字节流,再关闭文件等操作,而读取文件的过程就可以看作字节流的一个过程。常见的流类型有文件流、终端操作流、网络Socket等。

  在.NET中,System.IO.Stream类型被设计为所有流类型的虚基类,所有常见的流类型都继承自System.IO.Stream类型,当程序员需要自定义一种流类型时,也应该直接或者间接继承自Stream类型。.NET提供了丰富的内建的流类型,其中包括了操作文件的FileStream、操作内存的MemoryStream、操作网络的NetworkStream等。下图展示了.NET中常见的流类型以及它们的类型结构图。

  

  

 

  如上图所示,Stream类型继承自MarshalByRefObject类型,这保证了流类型可以跨越应用程序域进行交互。所有的常见的流类型都继承自System.IO.Stream类型,这保证了流类型的同一性。配合StreamReader和StreamWriter类型,.NET提供的流类型使用起来都非常简便,完全屏蔽了底部的一些复杂操作。

  以下代码以最常用的FileStream为例,介绍了流的使用方法。首先是从一个流读出所有字节和向下一个流传入所有字节的方法,这两个方法对于所有流对象是通用的。

using System;using System.Collections.Generic;using System.Text;using System.IO;namespace Test{    class UseStream    {        private const int bufferLength = 50;        static void Main()        {             //创建一个文件,并写入内容            string fileName = @"D:\TestStream.txt";            string fileContent = GetTestString();            try            {                //创建文件并写入内容                using (FileStream fs = new FileStream(fileName, FileMode.Create))                {                    byte[] bytes = Encoding.Default.GetBytes(fileContent);                    WriteAllBytes(fs, bytes, bufferLength);                    fs.Close();                }                //读取文件并且打印出来                using (FileStream fs = new FileStream (fileName,FileMode.Open))                {                    byte[] result = ReadAllBytes(fs, bufferLength);                    Console.WriteLine(Encoding.Default.GetString(result));                    Console.Read();                    fs.Close();                }            }            finally            {                try                {                    if (File.Exists(fileName))                    {                        File.Delete(fileName);                    }                }                finally                { }            }        }        //取得测试数据        static string GetTestString()        {            StringBuilder builder = new StringBuilder();            for (int i = 0; i < 10; i++)            {                builder.Append("我是测试数据\r\n");            }            return builder.ToString();        }                     //从一个流中读取所有字节        static byte[] ReadAllBytes(Stream stream, int bufferLength)        {             //读取的缓存            byte[] buffer = new byte[bufferLength];            List<byte> result = new List<byte>();            int read;            //直至读取结束            while ((read=stream.Read(buffer,0,bufferLength))>0)            {                if (read<bufferLength)                {                    byte[] temp = new byte[read];                    Array.Copy(buffer, temp, read);                    result.AddRange(temp);                }                else                {                    result.AddRange(buffer);                }            }            return result.ToArray();        }        //把字节写入一个流中        static void WriteAllBytes(Stream stream, byte[] data, int bufferLength)        {             //写入的缓存            byte[] buffer = new byte[bufferLength];            for (long i = 0; i < data.LongLength; i+=bufferLength)            {                int length = bufferLength;                if (i+bufferLength>data.LongLength)                {                    length = (int)(data.LongLength - i);                }                Array.Copy(data, i, buffer, 0, length);                stream.Write(buffer, 0, length);            }        }    }}

  由于优秀的封装,.NET中所有的流类型的使用方法都很类似,程序员基本可以无须关心底层实现的具体内容。当需要实现自定义的流类型时,程序员应该毫无疑问地使其直接或者间接地继承自Stream类型,以保证所有流类型的一致性。

  最后相当重要的一点是,Stream类型实现了IDisposable接口,所有对于流类型的使用都应该使用using语句确保Dispose方法被调用。

答案

  流是对于字节集合对象的一种操作。.NET中常见的流类型有FileStream、MemoryStream、NetworkStream、UnmanagedMemoryStream等。