手机
当前位置:查字典教程网 >编程开发 >C#教程 >.Net笔记:System.IO之Stream的使用详解
.Net笔记:System.IO之Stream的使用详解
摘要:Stream在msdn的定义:提供字节序列的一般性视图(providesagenericviewofasequenceofbytes)。这个...

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

常用的Stream的子类有:

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

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

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

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

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

下面看下如何操作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);

}

}

}

}

3. 使用Stream.Write方法向流中写字节数组

在使用Write方法时,需要先使用Stream的CanWrite方法判断流是否可写,如下示例定义了一个MemoryStream对象,然后向内存流中写入一个字节数组

复制代码 代码如下:

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();

}

}

}

4. 使用Stream.BeginWrite方法异步写;异步写可以提高程序性能,这是因为磁盘或者网络IO的速度远小于cpu的速度,异步写可以减少cpu的等待时间。

如下使用FileStream异步写文件的操作示例

复制代码 代码如下:

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();

}

}

}

}

【.Net笔记:System.IO之Stream的使用详解】相关文章:

深入多线程之:用Wait与Pulse模拟一些同步构造的应用详解

基于动态修改App.Config与web.Config的使用详解

深入多线程之:Wait与Pulse的使用详解

再议C#中的装箱与拆箱的问题详解

浅谈C#中Process类的使用详解

C#方法的总结详解

基于WebRequest.RegisterPrefix的使用详解

基于DateTime.ParseExact方法的使用详解

C#词法分析器之词法分析的使用详解

C# dynamic关键字的使用方法

精品推荐
分类导航