当前位置: 首页 > 编程日记 > 正文

.Net 文件流 System.IO之Stream

转自 :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

相关文章:

Hinton等人最新研究:大幅提升模型准确率,标签平滑技术到底怎么用?

作者 | Rafael Mller , Simon Kornblith, Geoffrey Hinton译者 | Rachel责编 | Jane出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09;【导读】损失函数对神经网络的训练有显著影响&#xff0c;也有很多学者人一直在探讨并寻找可以和损失函数一样使模型效果更好的函数…

WaitForSingleObject和WaitForMultipleObjects用法

转自&#xff1a;http://www.360doc.com/content/10/0512/09/1072296_27178529.shtml 等待函数可使线程自愿进入等待状态&#xff0c;直到一个特定的内核对象变为已通知状态为止。这些等待函数中最常用的是WaitForSingleObject: DWORD WaitForSingleObject(HANDLE hObject, DW…

【面试必问】支撑百万并发的IO多路复用技术你了解吗?

多路复用其实并不是什么新技术&#xff0c;它的作用是在一个通讯连接的基础上可以同时进行多个请求响应处理。对于网络通讯来其实不存在这一说法&#xff0c;因为网络层面只负责数据传输&#xff1b;由于上层应用协议的制订问题&#xff0c;导致了很多传统服务并不能支持多路复…

DllMain already defined in dllmain.obj错误

错误 uafxcw.lib(dllmodul.obj) : error LNK2005: DllMain already defined in dllmain.obj 修改: 去掉宏定义 _USRDLL 转载于:https://blog.51cto.com/co63oc/1122378

典型的数字水印软件

转自&#xff1a;http://blog.csdn.net/pastora/archive/2005/04/15/348413.aspx ---- 目前&#xff0c;数字水印软件既有商品化产品&#xff0c;也有供研究用的免费软件。 商品化软件 ----提供商品化数字水印软件的公司主要有以下一些&#xff1a; ----1&#xff0e;Digimar…

AI、5G、小程序、AIoT纷纷迎来高峰,下一步开发者们要怎么办?

2018 年&#xff0c;上千名开发者与上百名技术专家齐聚一堂&#xff0c;在 CSDN 2018 AI开发者大会上以“AI技术与应用”为核心&#xff0c;深度聚焦人工智能的技术创新与行业应用&#xff0c;真正做到了“只讲技术&#xff0c;拒绝空谈”。今年&#xff0c;在产业智能化的浪潮…

linux第四课

一、配置软件仓库1.yum简介基于rpm软件包的安装部署机制自动解决软件包的依赖关系需要先配置软件仓库2.配置本地的软件仓库a.放入centos7.iso镜像文件到光驱中&#xff0c;确保电源开启b.命令操作# umount /dev/cdrom# ls /mnt# mount /dev/cdrom /mnt# ls /mnt# mkdir -p /rep…

图像处理和图像识别中常用的CxImage函数

1、Load&#xff1a;reads from disk the image in a specific format&#xff1b; 2、Save&#xff1a;saves to disk the image in a specific format&#xff1b; 3、Filter&#xff1a;2D linear filter(图像锐化&#xff0c;可提高图像清晰度)&#xff1b; 4、Copy&…

大战三回合:XGBoost、LightGBM和Catboost一决高低 | 程序员硬核算法评测

作者 | LAVANYA译者 | 陆离责编 | Jane出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09;【导读】XGBoost、LightGBM 和 Catboost 是三个基于 GBDT&#xff08;Gradient Boosting Decision Tree&#xff09;代表性的算法实现&#xff0c;今天&#xff0c;我们将在三轮…

云计算之Docker介绍

1. 百科简介 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从Apache2.0协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。 容器是完全使用沙…

还在纠结垃圾分类问题?带你用Python感受ImageNet冠军模型SENet的强大

作者 | beyondma转载自CSDN博客本月1日起&#xff0c;上海正式开始了“史上最严“垃圾分类的规定&#xff0c;扔错垃圾最高可罚200元。全国其它46个城市也要陆续步入垃圾分类新时代。各种被垃圾分类逼疯的段子在社交媒体上层出不穷。其实从人工智能的角度看垃圾分类就是图像处理…

软件开发流程包含哪些内容

2019独角兽企业重金招聘Python工程师标准>>> 能否开发出一个好的软件&#xff0c;关键是看软件开发前期所做的工作&#xff0c;重点是这个软件有没有一个好的 软件开发流程&#xff0c;因为一个好的软件开发流程关系到到这个软件的成败和最后能达到一个什么的效果&a…

在对话框中应用CScrollView显示图像

1、用vs2008创建一个基于对话框的工程DialogView&#xff1b; 2、添加一个新类CMyDocument&#xff0c;基类为CDocument&#xff1b; 3、添加一个新类CMyView&#xff0c;基类为CScrollView&#xff1b; 4、修改CMyDocument的头文件&#xff1a; #pragma once // CMyDocument …

如何用纯 CSS 创作一个同心圆弧旋转 loader 特效

效果预览 在线演示 按下右侧的“点击预览”按钮在当前页面预览&#xff0c;点击链接全屏预览。 https://codepen.io/zhang-ou/pen/OZmXQX 可交互视频教程 此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。 请用 chrome, safari, edge 打开观看…

Java长见到的面试题,看你能答出几题,就知道自己有多菜了

作者&#xff1a;Java3y前言只有光头才能变强Redis目前还在看&#xff0c;今天来分享一下我在秋招看过(遇到)的一些面试题(相对比较常见的)0、final关键字简要说一下final关键字&#xff0c;final可以用来修饰什么&#xff1f;这题我是在真实的面试中遇到的&#xff0c;当时答得…

数据结构实验之链表一:顺序建立链表

题目描述 输入N个整数&#xff0c;按照输入的顺序建立单链表存储&#xff0c;并遍历所建立的单链表&#xff0c;输出这些数据。输入 第一行输入整数的个数N&#xff1b;第二行依次输入每个整数。输出 输出这组整数。示例输入 8 12 56 4 6 55 15 33 62 示例输出 12 56 4 6 55 15…

深度学习在人脸检测中的应用 | CSDN 博文精选

作者 | 梁志成、刘鹏、陈方杰责编 | 唐小引转载自CSDN&#xff08;ID:csdnnews&#xff09;在目标检测领域&#xff0c;可以划分为人脸检测与通用目标检测&#xff0c;往往人脸这方面会有专门的算法&#xff08;包括人脸检测、人脸识别、人脸其他属性的识别等&#xff09;&…

vs2008中,在OCX控件中应用doc/view基本步骤

1、利用向导创建一个MFC ActiveX Control控件CMyOCX&#xff1b; 2、在工程中加入ActivDoc头文件和执行文件&#xff1b; class CActiveXDocTemplate : public CSingleDocTemplate { enum { IDR_NOTUSED 0x7FFF }; CWnd* m_pParentWnd; CFrameWnd* m_pFrameWnd; C…

常见存储过程分页PK赛——简单测试分析常见存储过程分页速度

数据的分页是我们再熟悉不过的功能了&#xff0c;各种各样的分页方式层出不穷。今天我把一些常见的存储过程分页列出来&#xff0c;再简单地测一下性能&#xff0c;算是对知识的总结&#xff0c;也是对您好想法的抛钻引玉。废话不多说&#xff0c;开始吧~~ 1.首先建立一张测试表…

YOLOv3模型剪枝,瘦身80%,提速100%,精度基本不变

作者 | CV君转载自我爱计算机视觉&#xff08;ID: aicvml&#xff09;如果要在实际应用中部署目标检测&#xff0c;你会想到哪项算法&#xff1f;在52CV目标检测交流群里&#xff0c;被提及最多的&#xff0c;恐怕就是YOLOv3了。虽然新出的一些算法号称“完胜”“吊打”某某某算…

Ubuntu开发用新机安装流程

1.SSH安装 Ubuntu缺省已安装客户端&#xff0c;此处安装服务端 sudo apt-get install openssh-server 确认sshserver是否启动 netstat -tlp | grep ssh 或 ps -e | grep ssh 未启动&#xff0c;选择启动 sudo /etc/init.d/ssh start 2.问题解决&#xff1a;ACPI Error:Method p…

人工智能六十年技术简史

出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;作者&#xff1a;李理&#xff0c;环信人工智能研发中心vp&#xff0c;十多年自然语言处理和人工智能研发经验。主持研发过多款智能硬件的问答和对话系统&#xff0c;负责环信中文语义分析开放平台和环信智能机器人的设…

【Android游戏开发二十五】在Android上的使用《贝赛尔曲线》!

首先对于《赛贝尔曲线》不是很了解的童鞋&#xff0c;请自觉白度百科、google等等... 为了方便偷懒的童鞋&#xff0c;这里给个《贝赛尔曲线》百科地址&#xff0c;以及一段话简述《贝赛尔曲线》&#xff1a; 《贝赛尔曲线》白度百科快速地址&#xff1a;http://baike.baidu.co…

Spring Boot 工程集成全局唯一ID生成器 Vesta

2019独角兽企业重金招聘Python工程师标准>>> 本文内容脑图如下&#xff1a; 文章共 760字&#xff0c;阅读大约需要 2分钟 &#xff01; 概 述 在前一篇文章 《Spring Boot工程集成全局唯一ID生成器 UidGenerator》 中给大家推荐了一款由百度开发的基于 Snowflake算…

vs2008中,创建基于对话框的mfc动态库步骤

1、利用MFC Dll向导初始生成一个mfc dll(默认设置)&#xff1b; 2、添加一个对话框资源&#xff1b; 3、向工程中添加一个.h、.cpp文件&#xff0c;作为外部的接口&#xff1b; 4、.h头文件的格式仿照于基于控制台的dll的头文件格式&#xff1b; 5、.h头文件中包括资源文件头文…

poj3468 A Simple Problem with Integers

http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id14607 题意&#xff1a;题目给你n个数,m个操作&#xff0c;接下来一行给你这n个数&#xff0c;接下的几行给出m个操作&#xff0c;Q a b 表示查询区间[a,b]里的数和和。U a b c 表示把区间[a,b]里的数都加上c…

【Luogu】P1613 跑路

【Luogu】P1613 跑路 一、题目 题目描述 小A的工作不仅繁琐&#xff0c;更有苛刻的规定&#xff0c;要求小A每天早上在6&#xff1a;00之前到达公司&#xff0c;否则这个月工资清零。可是小A偏偏又有赖床的坏毛病。于是为了保住自己的工资&#xff0c;小A买了一个十分牛B的空间…

matlab图形用户界面设计简介

1、File->New->GUI->Create New GUI->Blank GUI->OK即可打开图形用户界面开发环境。 在里面可以拖放需要的控件&#xff0c;包括pushbutton、slider、radiobutton、togglebutton、checkbox、listbox、popupmenu、edit text、static text、table、axes、panel、…

旷视发布《人工智能应用准则》,倡导AI技术健康可持续发展

2019年7月8日&#xff0c;旷视宣布推出基于企业自身管理标准的《人工智能应用准则》&#xff08;以下简称《准则》&#xff09;&#xff0c;旨在从人工智能企业自身的角度&#xff0c;规范、引导人工智能技术正确运用和健康发展&#xff0c;并确保其安全可控可靠&#xff0c;促…

Java知识积累——String引用的判断问题

看如下程序 1 public static void main(String[] args) {2 String a new String("abc");3 String b new String("abc");4 System.out.println(a b); 5 6 String c "abc";7 String d "abc";8 …