关于Stream的知识分享

              一、什么是Stream

              查了一下MSDN,他是这么解释的:提供字节序列的一般视图。

              这个解释有点太笼统了,下面,我们来仔细的捋一下

              1、什么是字节序列?

              字节序列指的是:字节对象被存储为连续的字节序列,字节按照一定的顺序进行排序组成了字节序列。

              那么关于流的解释可以抽象为下列情况:

              一条河中有一条鱼游过,这条鱼就是一个字节,这个字节包括鱼的眼睛、嘴巴、等组成8个二进制,显然这条河就是我们的核心对象:流

              下面我们来认识一下C#中的Stream是如何使用的吧。

              二、Stream类的结构,属性和相关方法

              1、构造函数:

              Stream类有一个protected类型的构造函数,但是他是个抽象类,无法直接使用new来实例化。所以我们自定义一个流继承自Stream,看看哪些属性必须重写或自定义:

               1 public class MyStreamExample : Stream 
               2     {
               3 
               4         public override bool CanRead
               5         {
               6             get { throw new NotImplementedException(); }
               7         }
               8 
               9         public override bool CanSeek
              10         {
              11             get { throw new NotImplementedException(); }
              12         }
              13 
              14         public override bool CanWrite
              15         {
              16             get { throw new NotImplementedException(); }
              17         }
              18 
              19         public override void Flush()
              20         {
              21             throw new NotImplementedException();
              22         }
              23 
              24         public override long Length
              25         {
              26             get { throw new NotImplementedException(); }
              27         }
              28 
              29         public override long Position
              30         {
              31             get
              32             {
              33                 throw new NotImplementedException();
              34             }
              35             set
              36             {
              37                 throw new NotImplementedException();
              38             }
              39         }
              40 
              41         public override int Read(byte[] buffer, int offset, int count)
              42         {
              43             throw new NotImplementedException();
              44         }
              45 
              46         public override long Seek(long offset, SeekOrigin origin)
              47         {
              48             throw new NotImplementedException();
              49         }
              50 
              51         public override void SetLength(long value)
              52         {
              53             throw new NotImplementedException();
              54         }
              55 
              56         public override void Write(byte[] buffer, int offset, int count)
              57         {
              58             throw new NotImplementedException();
              59         }
              60     }

              可以看出系统自动帮我们实现了Stream的抽象属性和属性方法

              (1)CanRead:只读属性,判断该流是否能够读取;

              (2)CanSeek:只读属性,判断该流是否支持跟踪查找;

              (3)CanWrite:只读属性,判断当前流是否可写;

              (4)void Flush():当我们使用流写文件时,数据流会先进入到缓冲区中,而不会立刻写入文件,当执行这个方法后,缓冲区的数据流会立即写入基础流。

              (5)Length:流的长度;

              (6)Position:表示流中的一个位置。

              (7)abstract int Read(byte[] buffer,int offset,int count)

              这个方法包含了3个关键参数:缓冲字节数组,位偏移量和读取字节个数,每次读取一个字节后会返回一个缓冲区的总字节数

              第一个参数:这个数组相当于一个空盒子,Read() 方法每次读取流中的一个字节,将其放进这个空盒子中(全部读完后便可以使用buffer字节数组了)

              第二个参数:表示位移偏量,告诉我们从流中哪个位置(偏移量)开始读取。

              第三个参数:就是读取多少字节数。

              返回值:总共读取了多少字节数

              (8)abstract long Seek(long offset,SeekOrigin origin)

              大家还记的Position属性吗?其实Seek方法就是从新设定流中的一个位置。在说明offset参数作用之前大家先来了解下SeekOrigin这个枚举:

              分享图片

               

               如果offset为负,则要求 新位置位于origin制定的位置之前,其间隔相差offset制定的字节数。如果offset为0,则要求新位置位于由origin指定的位置处。如果offset为正,则要求新位置位于origin制定的位置后,其间隔相差offset制定的字节数。

              Stream.Seek(-3,Origin.End):表示在流末端往前第3个位置。

              Stream.Seek(0,Origin.Begin):表示在流的开头位置。

              Stream.Seek(3,Origin.Current):表示在流的当前位置往后数第3个位置。

              查找之后会返回一个流中的一个新位置,其实说到这大家就能理解Seek方法的精妙之处了吧。

              (9)abstract void Write(byte[] buffer,int offset,int count)

              这个方法包含3个关键参数:缓冲字节数组,位移偏量和读取字节个数和read方法,不同的是write方法中的第一个参数buffer已经有许多byte类型的数据,我们只需通过设置offset和count来将buffer中的数据写入流中。

              (10)virtual void Close()

              关闭流并释放资源,在实际操作中,如果不用using的话,别忘了使用完流之后将其关闭。

              为了让大家能够快速理解和消化上面的属性和方法,下面,我们写个示例:

               1 static void Main(string[] args)
               2         {
               3             byte[] buffer = null;
               4 
               5             string testString = "Stream!Hello world";
               6             char[] readCharArray = null;
               7             byte[] readBuffer = null;
               8             string readString = string.Empty;
               9             //关于MemoryStream 我会在后续章节详细阐述
              10             using (MemoryStream stream = new MemoryStream()) 
              11             {
              12                 Console.WriteLine("初始字符串为:{0}", testString);
              13                 //如果该流可写
              14                 if (stream.CanWrite)
              15                 {
              16                     //首先我们尝试将testString写入流中
              17                     //关于Encoding我会在另一篇文章中详细说明,暂且通过它实现string->byte[]的转换
              18                     buffer = Encoding.Default.GetBytes(testString);
              19                     //我们从该数组的第一个位置开始写,长度为3,写完之后 stream中便有了数据
              20                     //对于新手来说很难理解的就是数据是什么时候写入到流中,在冗长的项目代码面前,我碰见过很
              21                     //多新手都会有这种经历,我希望能够用如此简单的代码让新手或者老手们在温故下基础
              22                     stream.Write(buffer, 0,3);
              23 
              24                     Console.WriteLine("现在Stream.Postion在第{0}位置",stream.Position+1);
              25 
              26                     //从刚才结束的位置(当前位置)往后移3位,到第7位
              27                     long newPositionInStream =stream.CanSeek? stream.Seek(3, SeekOrigin.Current):0;
              28 
              29                     Console.WriteLine("重新定位后Stream.Postion在第{0}位置", newPositionInStream+1);
              30                     if (newPositionInStream < buffer.Length)
              31                     {
              32                         //将从新位置(第7位)一直写到buffer的末尾,注意下stream已经写入了3个数据“Str”
              33                         stream.Write(buffer, (int)newPositionInStream, buffer.Length - (int)newPositionInStream);
              34                     }
              35 
              36                     
              37                     //写完后将stream的Position属性设置成0,开始读流中的数据
              38                     stream.Position = 0;
              39 
              40                     // 设置一个空的盒子来接收流中的数据,长度根据stream的长度来决定
              41                     readBuffer = new byte[stream.Length];
              42 
              43 
              44                     //设置stream总的读取数量 ,
              45                     //注意!这时候流已经把数据读到了readBuffer中
              46                     int count = stream.CanRead?stream.Read(readBuffer, 0, readBuffer.Length):0;
              47          
              48 
              49                     //由于刚开始时我们使用加密Encoding的方式,所以我们必须解密将readBuffer转化成Char数组,这样才能重新拼接成string
              50 
              51                     //首先通过流读出的readBuffer的数据求出从相应Char的数量
              52                     int charCount = Encoding.Default.GetCharCount(readBuffer, 0, count);
              53                     //通过该Char的数量 设定一个新的readCharArray数组
              54                     readCharArray = new char[charCount];
              55                     //Encoding 类的强悍之处就是不仅包含加密的方法,甚至将解密者都能创建出来(GetDecoder()),
              56                     //解密者便会将readCharArray填充(通过GetChars方法,把readBuffer 逐个转化将byte转化成char,并且按一致顺序填充到readCharArray中)
              57                     Encoding.Default.GetDecoder().GetChars(readBuffer, 0, count, readCharArray, 0);
              58                     for (int i = 0; i < readCharArray.Length; i++)
              59                     {
              60                         readString += readCharArray[i];
              61                     }
              62                     Console.WriteLine("读取的字符串为:{0}", readString);
              63                 }
              64 
              65                 stream.Close();
              66             }
              67 
              68             Console.ReadLine();
              69 
              70         }

              结果:

              分享图片

               

               

               好了,关于流的基本介绍和概念,我们就分享到这里。非常感谢 逆时针の风 的博客对我的帮助

              相关文章
              相关标签/搜索
              每日一句
                每一个你不满意的现在,都有一个你没有努力的曾经。
              公众号推荐
                 一个历史类的公众号,欢迎关注
              一两拨千金
              香港蓝月亮精选免费资料大全管家婆王中王鉄算盘开奖结果2019开奖记录结果查询香港马会开奖结果历史纪录在线查询 准格尔旗| 徐汇区| 循化| 水城县| 宁强县| 绥宁县| 晋江市| 柏乡县| 梧州市| 蕉岭县| 京山县| 昭通市| 资阳市| 桃园市| 井研县| 巴中市| 汉源县| 泸溪县| 塘沽区| 山丹县| 徐州市| 博爱县| 吴桥县| 紫阳县| 天柱县| 天峨县| 温宿县| 塘沽区| 桓仁| 重庆市| 武强县| 临潭县| 隆安县| 辽宁省| 屯昌县| 芮城县| 夏邑县| 射洪县| 武清区| 卢龙县| 西城区| 定结县| 六枝特区| 荔波县| 凤阳县| 双柏县| 江永县| 威宁| 岑巩县| 封开县| 呼图壁县| 诏安县| 云浮市| 镇平县| 寻乌县| 恩施市| 深圳市| 德州市| 中牟县| 东山县| 龙井市| 故城县| 宣威市| 云浮市| 甘孜县| 定边县| 靖州| 浏阳市| 沅陵县| 岳池县| 巩义市| 汝南县| 郯城县| 永和县| 汤阴县| 朔州市| 治县。| 通道| 泰兴市| 内江市| 乌恰县| 军事| 金沙县| 卓尼县| 左云县| 黔南| 巩留县| 奉节县| 南漳县| 泾川县| 庆元县| 福泉市| 南汇区| 绵竹市| 绥江县| 东乡族自治县| 宁明县| 紫阳县| 嘉黎县| 内乡县| 辉南县| 新平| 阿克| 澎湖县| 遂溪县| 团风县| 佛学| 平乐县| 甘德县| 孝义市| 岢岚县| 潜山县| 绍兴市| 舞阳县| 莒南县| 柘荣县| 柳河县| 兖州市| 南川市| 桃源县| 会理县| 肇东市| 卢氏县| 新龙县| 本溪| 惠安县| 武穴市| 武宣县| 徐汇区| 二连浩特市| 德清县| 河曲县| 宜君县| 瑞安市| 黄陵县| 乌兰浩特市| 墨竹工卡县| 夏邑县| 额敏县| 普陀区| 闽清县| 高密市| 岑巩县| 宜州市| 竹溪县| 阜宁县| 仪陇县| 安福县| 永清县| 南昌市| 精河县| 台前县| 北川| 南澳县| 威远县| 天等县| 英山县| 鹤峰县| 桂平市| 湖口县| 天台县| 定襄县| 萨迦县| 舞阳县| 乌兰县| 浦县| 孝昌县| 汾西县| 田东县| 金平| 合江县| 扎囊县| 永寿县| 延庆县| 浙江省| 万全县| 阿克| 桐乡市| 吴堡县| 泸定县| 金寨县| 庆阳市| 沙田区| 崇义县| 兴仁县| 甘泉县| 栾城县| 阳原县| 克山县| 黑山县| 吉木萨尔县| 高邑县| 雷山县| 余干县| 和龙市| 五台县| 周口市| 彭阳县| 万全县| 永定县| 临桂县| 崇州市| 延川县| 蒲城县| 隆林| 汝南县| 新邵县| 洛阳市| 虎林市| 乳源| 神池县| 兰州市| 兰考县| SHOW| 桃园县| 济阳县| 濮阳市| 泽库县| 乐都县| 朝阳市| 延津县| 山东省| 五大连池市| 安达市| 昌宁县| 达拉特旗| 庆安县| 达日县| 亳州市| 海兴县| 新密市| 论坛| 新丰县| 蒙山县| 萨迦县| 阿拉善左旗| 谢通门县| 内乡县| 大丰市| 唐山市| 富川| 陵川县| 剑川县| 连江县| 尖扎县| 长岛县| 资源县| 察雅县| 河津市| 揭阳市| 盐边县| 中方县| 夏津县| 桐乡市| 芮城县| 马关县| 仙桃市| 准格尔旗| 察隅县| 张家界市| 萨嘎县| 山阳县| 文成县| 广汉市| 吉木萨尔县| 武陟县| 大新县| 扶风县| 綦江县| 麟游县| 宾川县| 垫江县| 杨浦区| 永和县| 凌云县| 安达市| 剑川县| 瓦房店市| 灌云县| 高台县| 衡水市| 汪清县| 张家港市| 正宁县| 永寿县| 晋城| 阳西县| 沐川县| 资阳市| 宁都县| 天镇县| 麻栗坡县| 陵川县| 城口县| 时尚| 湘西| 高雄县| 通榆县| 浦城县| 上高县| 武平县| 依兰县| 连山| 呼和浩特市| 台州市| 镇坪县| 岳西县| 玛多县| 大冶市| 高台县| 徐闻县| 本溪| 昂仁县| 灵石县| 温州市| 洮南市| 盐城市| 电白县| 宁明县| 郯城县| 林西县| 额敏县| 河池市| 大连市| 辽中县| 蒙自县| 鄂尔多斯市| 六盘水市| 府谷县| 容城县| 乾安县| 锦州市| 青浦区| 讷河市| 溧水县| 卢湾区| 股票| 修水县| 津南区| 宁明县| 信丰县| 吉隆县| 高淳县| 高州市| 洪泽县| 石门县| 南江县| 浪卡子县| 郁南县| 洛扎县| 麦盖提县| 什邡市| 海伦市| 陵川县| 刚察县| 从化市| 阿拉善右旗| 原平市| 大新县| 和顺县| 鹰潭市| 大竹县| 乾安县| 临沂市| 鹤壁市| 五华县| 壤塘县| 镇远县| 永善县| 临高县| 开江县| 永州市| 肥西县| 收藏| 尚义县| 大足县| 敦化市| 双流县| 泗阳县| 孟州市| 泸州市| 平乐县| 濮阳县| 永安市| 榆社县| 和平区| 丰宁| 分宜县| 通化市| 石泉县| 天峨县| 和田市| 中牟县| 沿河| 东城区| 余庆县| 桐梓县| 蒲江县| 陇川县| 聂荣县| 玉树县| 武清区| 翼城县| 二手房| 彭阳县| 永胜县| 东海县| 云林县| 红安县| 会宁县| 汕尾市| 油尖旺区| 肥东县| 彭州市| 麻江县| 格尔木市| 库尔勒市| 于田县| 出国| 长垣县| 仪征市| 出国| 高邮市| 襄汾县| 中方县| 江源县| 措勤县| 仙游县| 横山县| 方山县| 文昌市| 马关县| 吐鲁番市| 同德县| 新营市| 四平市| 闸北区| 齐齐哈尔市| 南陵县| 乌鲁木齐县| 泾川县| 罗源县| 措勤县| 勃利县| 汉源县| 科技| 通化市| 遂宁市| 墨脱县| 琼中| 崇礼县| 普兰店市| 澜沧| 定西市| 武鸣县| 九寨沟县| 济源市| 锡林郭勒盟| 怀柔区| 余干县| 晋州市| 若尔盖县| 吉隆县| 安福县| 琼结县| 建湖县| 梁山县| 改则县| 同心县| 大港区| 营山县| 老河口市| 桐城市| 宝应县| 沙雅县| 大埔县| 吴桥县| 广安市| 哈尔滨市| 泸州市| 扎兰屯市| 徐闻县| 泾川县| 三门县| 和龙市| 南汇区| 阜城县| 江阴市| 新乐市| 山东| 商城县| 四平市| 庆阳市| 泸西县| 宁陵县| 通州区| 普陀区| 若尔盖县| 麦盖提县| 衢州市| 开封市| 旬阳县| 云林县| 综艺| 区。| 平舆县| 安义县| 来安县| 清原| 海阳市| 五家渠市| 团风县| 民和| 定边县| 拜泉县| 普格县| 鸡东县| 茌平县| 莒南县| 池州市| 鹿邑县| 长乐市| 阜南县| 怀远县| 廊坊市| 乌恰县| 肥城市| 法库县| 长白| 宁海县| 洛浦县| 汝阳县| 九龙城区| 滦南县| 修武县| 什邡市| 文昌市| 白朗县| 越西县| 兴海县| 工布江达县| 台东县| 文山县| 祁阳县| 嘉善县| 宁河县| 英山县| 大连市| 绵阳市| 灵寿县| 滕州市| 乌兰县| 正镶白旗| 长海县| 延寿县| 涟水县| 东乌| 资阳市| 阳东县| 乐业县| 颍上县| 大化| 长兴县| 桦南县| 长宁县| 邮箱| 辉南县| 柯坪县| 牡丹江市| 郯城县| 社旗县| 顺昌县| 德兴市| 岳池县| 英德市| 兴义市| 文昌市| 崇仁县| 庄河市| 昌吉市| 临清市| 兰州市| 宁德市| 长武县| 科技| 卢湾区| 福清市| 南充市| 比如县| 华宁县| 渝北区| 旺苍县| 陆丰市| 峨眉山市| 岐山县| 公安县| 花莲县| 梁山县| 佛教| 淮安市| 华池县| 柏乡县| 兴山县| 玉门市| 扎兰屯市| 鄄城县| 海南省| 榕江县| 碌曲县| 安宁市| 丽江市| 惠安县| 昆山市| 阳原县| 张家川| http://m.jx1870guaranteev.fun http://m.jx1870fightv.fun http://www.jx1870landv.fun http://jx1870holev.fun http://m.jx1870establishv.fun http://www.jx1870holev.fun http://wap.jx1870holev.fun http://wap.jx1870exportv.fun http://jx1870labelv.fun http://hz0j3r3vo.fun http://www.jx1870flyv.fun http://jx1870fortv.fun http://wap.hz0j3r6vo.fun http://jx1870fullv.fun http://www.jx1870fruitv.fun http://wap.jx1870fuckv.fun http://www.jx1870ensurev.fun http://m.jx1870keyv.fun