C# MemoryStream类小结 (学习日记 2017-04-29)

MemoryStream类简介

MemoryStream类继承自Stream类,通过MemoryStream创建内存流(存储区放在内存中而不是磁盘),为系统内存提供读写操作。  
使用内存流的优点:
数据以无符号字节数组的形式保存在内存中,系统可以直接访问这些封装的数据而不必读取磁盘文件。更加贴近底层数据,读取的效率更高(读取速度更快,和文件流的主要区别),内存流可以降低系统对临时缓冲区和临时文件的需要。因此我们编程中常常用内存流作为中转,与其他流进行数据交换。(如利用MemoryStream操作文件,然后传给FileStream中)

MemoryStream的属性与方法

MemoryStream属性

属性来自MSDN官方解释,所谓的重写就是重写继承自Stream类的方法,只有一个属性是MemoryStream类独有的,就是Capacity,它是系统提供的字节数组的缓冲区长度,(Length是流的长度,以字节为单位)

CanRead      获取一个值,该值指示当前流是否支持读取。 (重写Stream.CanRead。)


CanTimeout  获取一个值,该值确定当前流是否可以超时。 (继承自Stream。)

CanWrite       获取一个值,该值指示当前流是否支持写入。 (重写Stream.CanWrite。)

Capacity        获取或设置分配给该流的字节数。

Length           获取用字节表示的流长度。 (重写 Stream.Length。)

Position         获取或设置流中的当前位置。 (重写 Stream.Position。)

ReadTimeout    获取或设置一个值(以毫秒为单位),该值确定流在超时前尝试读取多长时间。(继自 Stream

WriteTimeout   获取或设置一个值(以毫秒为单位),该值确定流在超时前尝试写入多长时间。(继自 Stream

            MemoryStream ms = new MemoryStream();              //创建一个内存流
            Console.WriteLine("ms是否可读:{0}",ms.CanRead);    //获取一个值,指示ms是否可读
            Console.WriteLine("ms是否可查找:{0}",ms.CanSeek);  //获取一个值,指示ms是否可查找
            Console.WriteLine("ms是否可写:{0}",ms.CanWrite);   //获取一个值,指示ms是否可写
            Console.WriteLine("ms是否支持超时:{0}",ms.CanTimeout);          //获取一个值,指示ms是否支持超时
            Console.WriteLine("更改之前的系统缓冲区大小:{0}",ms.Capacity); // 获取系统分配的缓冲区大小                                                               Console.WriteLine("流的长度:{0}",ms.Length);    //获取流的长度
            ms.Capacity = 1024;  //以字节为单位  1KB大小  capacity可读可写
            Console.WriteLine("更改之后的系统缓冲区大小:{0}",ms.Capacity);                                                                                           ms.ReadTimeout = 100; // 设置内存流超时前读取的时间,单位是毫秒
            ms.WriteTimeout = 100;// 设置内存流超时前写入的时间
            Console.ReadKey();

MemoryStream的方法

BeginRead      开始异步读操作。(从 Stream 继承) 


BeginWrite      开始异步写操作。(从 Stream 继承)


Close       关闭当前流并释放与之关联的所有资源(如套接字和文件句柄)(从 Stream 继承)


Dispose     释放资源(从 Stream 继承) 


EndRead     等待挂起的异步读取完成。(从 Stream 继承)


EndWrite     结束异步写操作。(从 Stream 继承) 


Flush       重写 Stream.Flush 以便不执行任何操作


GetBuffer     返回从其创建此流的无符号字节数组。 是会返回所有分配的字节,不管用没用到。


Read       从当前流中读取字节块并将数据写入 buffer 中。注意,Read()方法是从当前流的Position属性的位置开始读,这就是为什么很多人测试的时候,刚刚写入内存的数据,Read()方法无法读取到内容的原因,因为刚刚写入内存之后,位置恰好是在最后一位了。Read()方法当然读不到。此方法强大之处在于,你可以从一个内存流中读出你想要的一个片段。


ReadByte      从当前流中读取一个字节。(注意是按字节读取) (从 Stream 继承)


Seek        将当前流中的位置设置为指定值。(从 Stream 继承)


SetLength     将当前流的长度设为指定值。  (从 Stream 继承)


Synchronized    在指定的 Stream 对象周围创建线程安全(同步)包装。(从 Stream 继承)


ToArray      将整个流内容写入字节数组,而与 Position 属性无关。 


Write       使用从缓冲区读取的数据将字节块写入当前流。 注意下,第二个参数是第一个参数数组的偏移量就可以了。


WriteByte     将一个字节写入当前流中的当前位置。 (从 Stream 继承)


WriteTo     将此内存流的整个内容写入另一个流中。(常用在使用内存流向其他的流转换,如文件流)


方法测试实例

 注意三点:

一:所谓的缓冲区通常都是由字节数组构成,MemoryStream可以方便快捷的使用字节数组进行读和写。

二:使用MemoryStream时要注意流的索引位置,也就是Position属性,如刚刚写入数据,那么Position的位置在数据的最后,如果不进行设置,是无法使用Read和ReadByte读取流的数据的。

三:注意将字符串转换成字节数组将字节数组转化成字符串的思路,这是自己缺失的一部分(使用相同的对象进行转换)

            MemoryStream ms = new MemoryStream();
            byte[] buffer = Encoding.UTF8.GetBytes("shileizhenshiyigedahaoren");  //一般缓冲区都是由字节数组构成
            
            ms.Write(buffer,0,6);   //从缓冲区读取数据写入到流中,
            byte[] result1 = ms.GetBuffer(); //返回写入内存流的原流数据
            string turnStr = Encoding.UTF8.GetString(result1);   //将字节数组转换成字符串。
            Console.WriteLine(turnStr);

            ms.Seek(4,SeekOrigin.Begin);  //将流的当前位置设置为开始的位置
            int i = ms.ReadByte();  //读取一个字节,如果达到了流的末尾则为-1,返回字节的ASCII码
            Console.WriteLine("流的当前位置:{0}",i.ToString());

            byte[] result2 = ms.ToArray();  //流返回一个字节数组,缓冲区, 类似GetBuffer
            foreach (var item in result2)   
            {
                Console.Write(item.ToString() + "-");   
            }


            MemoryStream ms2 = new MemoryStream();  
            byte[] buffer2 = Encoding.UTF8.GetBytes("这个世界真的很美好"); //utf-8中,一个汉字三个字节
            ms2.Write(buffer2,0,buffer2.Length); //参数1写入的数据源,参数2数据源的开始索引,参数3写入长度
            Console.WriteLine("\n"+ms2.Position); //position可以理解为ms中的指针,写完数据后,指针在最后一位

            int j = ms2.ReadByte();  //索引Position在最后一位,所以返回的值为-1,表示在最后
            Console.WriteLine("写入数据后当前指针指向的值:{0}", j.ToString());

            ms2.Position = 0;  //设置索引在第一位
            int k = ms2.ReadByte();
            Console.WriteLine("改变指针后的值:{0}", k.ToString());
            Console.ReadKey();



 

MemoryStream实例

利用XmlWritter与MemoryStream写数据,实现了MemoryStream和FileStream的转换,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;


namespace test001
{
    class Program
    {
        static void Main(string[] args)
        {
            MemoryStream ms = new MemoryStream();
            using (ms)   // 确保程序在代码段结束的时候dispose掉ms
            {
                XmlWriter writer = XmlWriter.Create(ms); //创建一个Xmlwriter对象
                using (writer)  //确保在程序在代码段结束时调用Dispose
                {
                    writer.WriteStartDocument(true);     //写入Xml头
                    writer.WriteStartElement("Content"); //写入元素
                    writer.WriteStartAttribute("Test");  //写入属性
                    writer.WriteValue("往事都随风!");   //写入属性值
                    writer.Flush();                      //释放缓冲
                    Console.WriteLine("此时内容使用量:{0}KB \n 该memoryStream已经使用容量:{1}Byte \n 默认容量{2}", Math.Round((double)ms.Length, 4), ms.Capacity, GC.GetTotalMemory(false) / 1024);          
                    Console.WriteLine("重定位MemoryStream的位置{0}", ms.Position); //输出ms的现在所在的位置
                    ms.Seek(7, SeekOrigin.Current);
                    Console.WriteLine("重定位后MemoryStream的位置{0}", ms.Position);
                    writer.WriteStartElement("Content2");
                    writer.WriteStartAttribute("Test");
                    writer.WriteValue("不想随风了!");
                    writer.WriteEndElement();
                    writer.WriteEndElement();

                    writer.Flush();  //释放资源
                    Console.WriteLine("此时内容使用量:{0}KB \n 该memoryStream已经使用容量:{1}Byte \n 默认容量{2}", Math.Round((double)ms.Length, 4), ms.Capacity, GC.GetTotalMemory(false) / 1024);

                    string path = @"G:\test.xml";
                    FileStream fs = new FileStream(path, FileMode.OpenOrCreate);
                    ms.WriteTo(fs); //把ms写入到fs中去   writeto
                    fs.Flush();
                    Console.ReadKey();
                }
            }
        }
    }
}


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值