.NET文件流详解:System.IO之Stream

日期: 2012-04-23 来源:TechTarget中国 英文

  Stream在msdn的定义:提供字节序列的一般性视图(provides a generic view of a sequence of bytes)。这个解释太抽象了,不容易理解;从stream的字面意思“河,水流”更容易理解些,stream是一个抽象类,它定义了类似“水流”的事物的一些统一行为,包括这个“水流”是否可以抽水出来(读取流内容);是否可以往这个“水流”中注水(向流中写入内容);以及这个“水流”有多长;如何关闭“水流”,如何向“水流”中注水,如何从“水流”中抽水等“水流”共有的行为。

  常用的Stream的子类有:

  1) MemoryStream 存储在内存中的字节流

  2) FileStream 存储在文件系统的字节流

  3) NetworkStream 通过网络设备读写的字节流

  4) BufferedStream 为其他流提供缓冲的流

  Stream提供了读写流的方法是以字节的形式从流中读取内容。而我们经常会用到从字节流中读取文本或者写入文本,微软提供了StreamReaderStreamWriter类帮我们实现在流上读写字符串的功能。

  下面看下如何操作Stream,即如何从流中读取字节序列,如何向流中写字节

  1.使用Stream.Read方法从流中读取字节,如下示例注释:

  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.IO;
  namespace UseStream
  {
      class Program
      {
          //示例如何从流中读取字节流
          static void Main(string[] args)
          {
              var bytes = new byte[] {(byte)1,(byte)2,(byte)3,(byte)4,(byte)5,(byte)6,(byte)7,(byte)8};
              using (var memStream = new MemoryStream(bytes))
              {
                  int offset = 0;
                  int readOnce = 4;
                 
                  do
                  {
                      byte[] byteTemp = new byte[readOnce];
                      // 使用Read方法从流中读取字节
                      //第一个参数byte[]存储从流中读出的内容
                      //第二个参数为存储到byte[]数组的开始索引,
                      //第三个int参数为一次最多读取的字节数
                      //返回值是此次读取到的字节数,此值小于等于第三个参数
                      int readCn = memStream.Read(byteTemp, 0, readOnce);
                      for (int i = 0; i < readCn; i++)
                      {
                          Console.WriteLine(byteTemp[i].ToString());
                      }
                     
                      offset += readCn;
                      //当实际读取到的字节数小于设定的读取数时表示到流的末尾了
                      if (readCn < readOnce) break;
                  } while (true);
              }
  
              Console.Read();
          }
      }
  }
 
  2.使用Stream.BeginRead方法读取FileStream的流内容

  注意:BeginRead在一些流中的实现和Read完全相同,比如MemoryStream;而在FileStream和NetwordStream中BeginRead就是实实在在的异步操作了。

  如下示例代码和注释:

  using System; 
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.IO;
  using System.Threading;
  namespace UseBeginRead
  {
      class Program
      {
          //定义异步读取状态类
          class AsyncState
          {
              public FileStream FS { get; set; }
              public byte[] Buffer { get; set; }
              public ManualResetEvent EvtHandle { get; set; }
          }
          static  int bufferSize = 512;
          static void Main(string[] args)
          {
              string filePath = “d:\test.txt”;
              //以只读方式打开文件流
              using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
              {
                  var buffer = new byte[bufferSize];
                  //构造BeginRead需要传递的状态
                  var asyncState = new AsyncState { FS = fileStream, Buffer = buffer ,EvtHandle = new ManualResetEvent(false)};
                  //异步读取
                  IAsyncResult asyncResult = fileStream.BeginRead(buffer, 0, bufferSize, new AsyncCallback(AsyncReadCallback), asyncState);
                  //阻塞当前线程直到读取完毕发出信号
                  asyncState.EvtHandle.WaitOne();
                  Console.WriteLine();
                  Console.WriteLine(“read complete”);
                  Console.Read();
              }
          }
          //异步读取回调处理方法
          public static void AsyncReadCallback(IAsyncResult asyncResult)
          {
              var asyncState = (AsyncState)asyncResult.AsyncState;
              int readCn = asyncState.FS.EndRead(asyncResult);
              //判断是否读到内容
              if (readCn > 0)
              {
                  byte[] buffer;
                  if (readCn == bufferSize) buffer = asyncState.Buffer;
                  else
                  {
                      buffer = new byte[readCn];
                      Array.Copy(asyncState.Buffer, 0, buffer, 0, readCn);
                  }
                  //输出读取内容值
                  string readContent = Encoding.UTF8.GetString(buffer);
                 
                  Console.Write(readContent);
              }
              if (readCn < bufferSize)
              {
                  asyncState.EvtHandle.Set();
              }
              else {
                  Array.Clear(asyncState.Buffer, 0, bufferSize);
                  //再次执行异步读取操作
                  asyncState.FS.BeginRead(asyncState.Buffer, 0, bufferSize, new AsyncCallback(AsyncReadCallback), asyncState);
              }
          }
      }
  }

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国