黑马程序员技术交流社区
标题: .NET 文件流详解:System.IO之Stream [打印本页]
作者: 郑昱曦 时间: 2012-11-14 14:14
标题: .NET 文件流详解:System.IO之Stream
本帖最后由 郑昱曦 于 2012-11-14 14:16 编辑
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();
- }
- }
- }<span style="background-color: white; color: rgb(0, 0, 0); font-family: SimSun; font-size: 14px; line-height: 23px;"> </span>
复制代码 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();
- }
- }
- }
复制代码
作者: 许庭洲 时间: 2012-11-14 20:56
值得学习ing!
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |