转自 :http://www.cnblogs.com/yukaizhao/archive/2011/07/28/stream.html

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方法从流中读取字节,如下示例注释:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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就是实实在在的异步操作了。

如下示例代码和注释:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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对象,然后向内存流中写入一个字节数组

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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();
            }
        }
    }
}

转载于:https://www.cnblogs.com/IT-Bear/archive/2013/01/18/2865848.html

.Net 文件流 System.IO之Stream相关推荐

  1. JAVA mac系统io文件流_Java IO流基础1--IO的分类体系与文件流

    什么是IO流 Java中的IO 了解什么是IO流之前,要先知道什么是IO.IO,就是in和out(即输入和输出),指应用程序和外部设备之间的数据传递,常见的外部设备包括文件.管道.网络连接等. 流的概 ...

  2. java多线程运行结果写入文件错误java.io.IOException: Stream closed

    今天在写多线程程序的时候,需要将每个线程运行的结果写入同一个文件,用的是FileWriter,最后在关闭写入流的时候出现如下问题: java.io.IOException: Stream closed ...

  3. c++语言文件流,C++ IO类、文件输入输出、string流详细讲解

    新的C++标准中有三分之二的内容都是描述标准库.接下来重点学习其中几种核心库设施,这些是应该熟练掌握的. 标准库的核心是很多容器类(顺序容器和关联容器等)和一簇泛型算法(该类算法通常在顺序容器一定范围 ...

  4. 服务器 网络文件夹,System.IO.FileSystemWatcher监视网络服务器文件夹 - 性能注意事项(Sys...

    我想看更改网络服务器上的文件夹树. 这些文件都具有特定的扩展. 有树约200文件夹和带我看的延长约1200文件. 我不能写一个服务,在服务器上运行(禁地!),所以解决方案必须是本地的客户端. 及时性不 ...

  5. C++之文件流操作(File Stream)

    目录 一.引言 二.文件流对象(fstream) 2.1 流对象的定义 2.2 流对象关联文件 2.2.1 .open 函数 2.2.2 关闭流对象(close 函数) 三. 文件读写 3.1 读写文 ...

  6. 字节流转化为文件流_JAVA IO分析一:File类、字节流、字符流、字节字符转换流...

    因为工作事宜,又有一段时间没有写博客了,趁着今天不是很忙开始IO之路:IO往往是我们忽略但是却又非常重要的部分,在这个讲究人机交互体验的年代,IO问题渐渐成了核心问题. 一.File类 在讲解File ...

  7. 接收大文件流_一文搞定 Node.js 流 (Stream)

    stream(流)是一种抽象的数据结构.就像数组或字符串一样,流是数据的集合. 不同的是,流可以每次输出少量数据,而且它不用存在内存中. 比如,对服务器发起 http 请求的 request/resp ...

  8. C#数据流:文件流、内存流、网络流

    全栈工程师开发手册 (作者:栾鹏) c#教程全解 C#编程中数据流的使用一直不很熟练,没有一个系统的认识,但是它的重要性显然不言而喻.System.IO下的Stream类是所有数据流的基类,当我们对数 ...

  9. Java 方法、 流(Stream)、文件(File)和IO 总结

    这里只总结几个要点. 1. 方法的命名规则 1.方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符.例如:addPerson. 2.下划线可能出现在 JUnit 测 ...

最新文章

  1. C#的静态方法与静态成员(转)
  2. C#中多线程 委托的使用
  3. Winform中使用Timer实现滚动字幕效果(附代码下载)
  4. esp32原理图设计_第十一章 ESP32的PWM全彩LED灯显示
  5. java实现ftp文件的上传与下载
  6. 笔记本长时间不用出现一片黑屏
  7. C#算法设计排序篇之10-桶排序(附带动画演示程序)
  8. python接口自动化(五)--接口测试用例和接口测试报告模板(详解)
  9. linux 虚拟 设备,Linux中的虚拟网络设备
  10. LINUX获得线程号、设置线程名
  11. html如何转换成中文,html中文乱码怎么解决怎么造成如何避免中文乱码
  12. 什么叫计算机硬件特征码,如何检测电脑的硬件特征码信息(主板、CPU、硬盘)...
  13. 关于WireShark跟随数据流后entire conversation显示的字节数分析
  14. win10获得system权限(超级管理员)
  15. 【2021-04-25】APP逆向之某智网加密数据
  16. java内部模型,13 张图拆解 Java 中的内存模型
  17. WCF从理论到实践(3):八号当铺之黑色契约
  18. WebClient概述
  19. Educational Codeforces Round 116 (Rated for Div. 2) A B C
  20. OpenGL ES学习(8)——剪裁测试认识

热门文章

  1. 百万级访问量网站的技术准备工作[转帖]
  2. RHEL5 install
  3. iOS RunLoop详解
  4. 如何重构“箭头型”代码
  5. 怎么写shell脚本才能不耍流氓?
  6. 云计算重构渠道商的价值基础,推动渠道商向服务商转型
  7. 0627 - 不能再靠功能取胜
  8. redis 运维常用命令
  9. 控制语句 for while if switch
  10. Mysql备份与还原及优化方法