源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

.Net笔记:System.IO之Stream的使用详解

  • 时间:2022-01-19 10:03 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:.Net笔记:System.IO之Stream的使用详解
Stream在msdn的定义:提供字节序列的一般性视图(provides a generic view of a sequence of bytes)。这个解释太抽象了,不容易理解;从stream的字面意思“河,水流”更容易理解些,stream是一个抽象类,它定义了类似“水流”的事物的一些统一行为,包括这个“水流”是否可以抽水出来(读取流内容);是否可以往这个“水流”中注水(向流中写入内容);以及这个“水流”有多长;如何关闭“水流”,如何向“水流”中注水,如何从“水流”中抽水等“水流”共有的行为。 [b]常用的Stream的子类有: [/b]1) MemoryStream 存储在内存中的字节流 2) FileStream  存储在文件系统的字节流 3) NetworkStream 通过网络设备读写的字节流 4) BufferedStream 为其他流提供缓冲的流 Stream提供了读写流的方法是以字节的形式从流中读取内容。而我们经常会用到从字节流中读取文本或者写入文本,微软提供了StreamReader和StreamWriter类帮我们实现在流上读写字符串的功能。 下面看下如何操作Stream,即如何从流中读取字节序列,如何向流中写字节 [b]1. 使用Stream.Read方法从流中读取字节,如下示例注释: [/b]
[u]复制代码[/u] 代码如下:
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();         }     } }
[b]2. 使用Stream.BeginRead方法读取FileStream的流内容 [/b]注意:BeginRead在一些流中的实现和Read完全相同,比如MemoryStream;而在FileStream和NetwordStream中BeginRead就是实实在在的异步操作了。 如下示例代码和注释:
[u]复制代码[/u] 代码如下:
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);             }         }     } }
[b]3. 使用Stream.Write方法向流中写字节数组 [/b]在使用Write方法时,需要先使用Stream的CanWrite方法判断流是否可写,如下示例定义了一个MemoryStream对象,然后向内存流中写入一个字节数组
[u]复制代码[/u] 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace UseStreamWrite {     class Program     {         static void Main(string[] args)         {             using (var ms = new MemoryStream())             {                 int count = 20;                 var buffer = new byte[count];                 for (int i = 0; i < count; i++)                 {                     buffer[i] = (byte)i;                 }                 //将流当前位置设置到流的起点                 ms.Seek(0, SeekOrigin.Begin);                 Console.WriteLine("ms position is " + ms.Position);                 //注意在调用Stream的Write方法之前要用CanWrite判断Stream是否可写                 if (ms.CanWrite)                 {                     ms.Write(buffer, 0, count);                 }                 //正确写入的话,流的位置会移动到写入开始位置加上写入的字节数                 Console.WriteLine("ms position is " + ms.Position);             }             Console.Read();         }     } }
[b]4. 使用Stream.BeginWrite方法异步写;异步写可以提高程序性能,这是因为磁盘或者网络IO的速度远小于cpu的速度,异步写可以减少cpu的等待时间。 [/b]如下使用FileStream异步写文件的操作示例
[u]复制代码[/u] 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Threading; namespace UseStreamBeginWrite {     class Program     {         /// <summary>         /// 异步回调需要的参数封装类         /// </summary>         class AsyncState {             public int WriteCountOnce { get; set; }             public int Offset { get; set; }             public byte[] Buffer { get; set; }             public ManualResetEvent WaitHandle { get; set; }             public FileStream FS { get; set; }         }         static void Main(string[] args)         {             //准备一个1K的字节数组             byte[] toWriteBytes = new byte[1 << 10];             for (int i = 0; i < toWriteBytes.Length; i++)             {                 toWriteBytes[i] = (byte)(i % byte.MaxValue);             }             string filePath = "d:\\test.txt";             //FileStream实例             using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))             {                 int offset = 0;                 //每次写入32字节                 int writeCountOnce = 1 << 5;                 //构造回调函数需要的状态                 AsyncState state = new AsyncState{                     WriteCountOnce = writeCountOnce,                     Offset = offset,                     Buffer = toWriteBytes,                     WaitHandle = new ManualResetEvent(false),                     FS = fileStream                 };                 //做异步写操作                 fileStream.BeginWrite(toWriteBytes, offset, writeCountOnce, WriteCallback, state);                 //等待写完毕或者出错发出的继续信号                 state.WaitHandle.WaitOne();             }             Console.WriteLine("Done");             Console.Read();         }         /// <summary>         /// 异步写的回调函数         /// </summary>         /// <param name="asyncResult">写状态</param>         static void WriteCallback(IAsyncResult asyncResult)         {             AsyncState state = (AsyncState)asyncResult.AsyncState;             try             {                 state.FS.EndWrite(asyncResult);             }             catch (Exception ex)             {                 Console.WriteLine("EndWrite Error:" + ex.Message);                 state.WaitHandle.Set();                 return;             }             Console.WriteLine("write to " + state.FS.Position);             //判断是否写完,未写完继续异步写             if (state.Offset + state.WriteCountOnce < state.Buffer.Length)             {                 state.Offset += state.WriteCountOnce;                 Console.WriteLine("call BeginWrite again");                 state.FS.BeginWrite(state.Buffer, state.Offset, state.WriteCountOnce, WriteCallback, state);             }             else {                 //写完发出完成信号                 state.WaitHandle.Set();             }         }     } }
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部