MemoryStream位于System.IO命名空间,为系统内存提供流式的读写操作。常作为其他流数据交换时的中间对象操作。

1、MemoryStream类封装一个字节数组,在构造实例时可以使用一个字节数组作为参数,但是数组的长度无法调整。使用默认无参数构造函数创建实例,可以使用Write方法写入,随着字节数据的写入,数组的大小自动调整。

2、在对MemoryStream类中数据流进行读取时,可以使用seek方法定位读取器的当前的位置,可以通过指定长度的数组一次性读取指定长度的数据。ReadByte方法每次读取一个字节,并将字节返回一个整数值。

3、UnicodeEncoding类中定义了Unicode中UTF-16编码的相关功能。通过其中的方法将字符串转换为字节,也可以将字节转换为字符串。
MemoryStream 是一个特例,MemoryStream中没有任何非托管资源,所以它的Dispose不调用也没关系。托管资源.Net会自动回收

MemoryStream继承自Stream类。内存流的好处是指针可以晃来晃去,也就是支CanSeek,Position,Seek()。任意读其中一段。

在内存流中有必要了解一下SeekOrigin枚举

枚举成员 成员值 描述
Begin 0 指定流的开头。
Current 1 指定流内的当前位置。
End 2 指定流的结尾。

MemoryStream提供的属性与方法:
一、属性

CanRead     已重写。获取一个值,该值指示当前流是否支持读取。
CanSeek     已重写。获取一个值,该值指示当前流是否支持查找。
CanTimeout    获取一个值,该值确定当前流是否可以超时。(从 Stream 继承。)
CanWrite     已重写。获取一个值,该值指示当前流是否支持写入。
Capacity     获取或设置分配给该流的字节数。 这个是分配的字节数
Length      已重写。获取用字节表示的流长度。这个是真正占用的字节数。
Position      已重写。获取或设置流中的当前位置。
ReadTimeout   获取或设置一个值,该值确定流在超时前尝试读取多长时间。 (从 Stream 继承。)
WriteTimeout   获取或设置一个值,该值确定流在超时前尝试写入多长时间。 (从 Stream 继承。)

二、方法

BeginRead     开始异步读操作。 (从 Stream 继承。)
BeginWrite    开始异步写操作。 (从 Stream 继承。)
Close        关闭当前流并释放与之关联的所有资源(如套接字和文件句柄)。 (从 Stream 继承。)
CreateObjRef   创建一个对象,该对象包含生成用于与远程对象进行通信的代理所需的全部相关信息。 (从 MarshalByRefObject 继承。)
Dispose      已重载。
EndRead     等待挂起的异步读取完成。 (从 Stream 继承。)
EndWrite      结束异步写操作。 (从 Stream 继承。)
Flush        已重写。 重写 Stream.Flush 以便不执行任何操作。
GetBuffer     返回从其创建此流的无符号字节数组。 是会返回所有分配的字节,不管用没用到。
GetLifetimeService      检索控制此实例的生存期策略的当前生存期服务对象。 (从 MarshalByRefObject 继承。)
InitializeLifetimeService   获取控制此实例的生存期策略的生存期服务对象。 (从 MarshalByRefObject 继承。)
Read            已重写。 从当前流中读取字节块并将数据写入 buffer 中。 搞了好久才弄明白Read()方法的含义,第一个参数,是读取到的内容要输出到的字节数组,第二个参数是放在第一个参数即要输出的数组的位置的偏移量,第三个参数是,要读取的字符数。 用这个方法你可以任意读取一段需要的内存。注意,Read()方法是从当前流的Position属性的位置开始读,这就是为什么很多人测试的时候,刚刚写入内存的数据,Read()方法无法读取到内容的原因,因为刚刚写入内存之后,位置恰好是在最后一位了。Read()方法当然读不到。此方法强大之处在于,你可以从一个内存流中读出你想要的一个片段。
ReadByte          已重写。 从当前流中读取一个字节。
Seek            已重写。 将当前流中的位置设置为指定值。
SetLength          已重写。 将当前流的长度设为指定值。
Synchronized        在指定的 Stream 对象周围创建线程安全(同步)包装。 (从 Stream 继承。)
ToArray          将整个流内容写入字节数组,而与 Position 属性无关。
Write            已重写。 使用从缓冲区读取的数据将字节块写入当前流。 同样注意下,第二个参数是第一个参数数组的偏移量就可以了。
WriteByte         已重写。 将一个字节写入当前流中的当前位置。
WriteTo          将此内存流的整个内容写入另一个流中。

以下给出使用示例代码:

  1.  
    static void Main(string[] args)
  2.  
    {
  3.  
    //属性测试
  4.  
    MemoryStream ms = new MemoryStream();
  5.  
    Console.WriteLine(ms.CanRead); //True 内存流可读
  6.  
    Console.WriteLine(ms.CanSeek); //True 内存流支持查找,指针移来移去的查找
  7.  
    Console.WriteLine(ms.CanTimeout); //False 内存流不支持超时
  8.  
    Console.WriteLine(ms.CanWrite); //True 内存流可写
  9.  
     
  10.  
    Console.WriteLine(ms.Capacity); //0 分配给该流的字节数
  11.  
    byte[] bytes = Encoding.UTF8.GetBytes("abcdedcba");
  12.  
    ms.Write(bytes, 0, bytes.Length); //已将一段文本写入内存
  13.  
    Console.WriteLine(ms.Capacity); //256 再次读取为文本流分配的字节数已经变成了256,看来内存流是根据需要的多少来分配的
  14.  
    Console.WriteLine(ms.Length); //9 这个是流长度,通常与英文的字符数一样,真正占用的字节数。
  15.  
     
  16.  
    Console.WriteLine(ms.Position); //9 流当前的位置,该属性可读可设置
  17.  
     
  18.  
    //Console.WriteLine(ms.ReadTimeout); 由于流不支持超时,此属性如果读取或者设置的话会报错
  19.  
    //Console.WriteLine(ms.WriteTimeout); 由于流不支持超时,此属性如果读取或者设置的话会报错
  20.  
     
  21.  
    //方法测试
  22.  
    byte[] byte1 = ms.GetBuffer(); //返回无符号字节数组 差点被忽悠了,无符号字节数组 其实就是byte(0~255),有符号字节sbyte(-128~127)
  23.  
    string str1 = Encoding.UTF8.GetString(byte1);
  24.  
    Console.WriteLine(str1); //输出 abcdedcba
  25.  
     
  26.  
    ms.Seek(2, SeekOrigin.Current); //设置当前流正在读取的位置 为开始位置即从0开始
  27.  
    //从内存中读取一个字节
  28.  
    int i = ms.ReadByte();
  29.  
    Console.WriteLine(i); //输出99
  30.  
    byte[] bytes3 = ms.ToArray();
  31.  
    foreach (byte b in bytes3)
  32.  
    {
  33.  
    Console.Write(b + "-");//用于对比 输出 97-98-99-100-101-100-99-98-97- 可以看到 0,1,2第二位刚好是99
  34.  
    }
  35.  
     
  36.  
    MemoryStream ms2 = new MemoryStream();
  37.  
    byte[] bytes6 = Encoding.UTF8.GetBytes("abcde");
  38.  
    ms2.Write(bytes6, 0, bytes6.Length);
  39.  
    Console.WriteLine(ms2.Position); //输出5 写完之后流的位置就到了最后,因此想用read读取必须加下面这一行代码。
  40.  
     
  41.  
    //ms2.Seek(0, SeekOrigin.Begin); //想要用Read方法读取完整的流,必须设置当前位置,Read是从Position的位置开始读。
  42.  
    ms2.Position = 0; //Read是从当前位置开始读,这行代码和上面一行意义一样。
  43.  
    byte[] byteArray = new byte[5] { 110, 110, 110, 110, 110 }; //99是经过YTF8解码之后是 n
  44.  
    ms2.Read(byteArray, 2, 1); //读取一个字节,byteArray的第一个元素中,(注意从0开始)
  45.  
    Console.WriteLine(Encoding.UTF8.GetString(byteArray)); //nnann
  46.  
    //ms2.Read(byteArray, 2, 2);
  47.  
    //Console.WriteLine(Encoding.UTF8.GetString(byteArray)); //nnabn //当超出接收数组总长度的时候,后面的元素会被移开
  48.  
     
  49.  
     
  50.  
    //设置当前流的长度
  51.  
    Console.WriteLine(ms.Length); //输出9 当前流的长度是9
  52.  
    ms.SetLength(20);
  53.  
    Console.WriteLine(ms.Length); //输出20
  54.  
    foreach (byte b in ms.ToArray()) //将流的内容也就是内存中的内容转换字节数组
  55.  
    {
  56.  
    Console.Write(b + "-"); //输出 97-98-99-100-101-100-99-98-97-0-0-0-0-0-0-0-0-0 由于设置了长度,因此空的自动补0
  57.  
    }
  58.  
    Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); //输出 abcdedcba 虽然长度变长了,但是没影响读取数据
  59.  
     
  60.  
    MemoryStream ms1 = new MemoryStream();
  61.  
    byte[] bytes4 = ms1.ToArray();
  62.  
    Console.WriteLine("此内存流并没有写入数据(Write)" + Encoding.UTF8.GetString(bytes4));//输出 此内存流并没有写入数据(Write) 因为内存为空
  63.  
     
  64.  
     
  65.  
    //下面来一个指定位置的写入
  66.  
    MemoryStream ms3 = new MemoryStream();
  67.  
    byte[] bytesArr = Encoding.ASCII.GetBytes("abcdefg");
  68.  
    ms3.Write(bytesArr, 0, bytesArr.Length);
  69.  
    ms3.Position = 2;
  70.  
    ms3.WriteByte(97); //97代表的是a 这段代码的意思是,将原先第二个的c替换为a
  71.  
    string str = Encoding.ASCII.GetString(ms3.ToArray());
  72.  
    Console.WriteLine(str); //输出 abacdefg
  73.  
     
  74.  
    byte[] byteArr1 = Encoding.ASCII.GetBytes("kk");
  75.  
    ms3.Position = 4;
  76.  
    ms3.Write(byteArr1, 0, byteArr1.Length);
  77.  
    Console.WriteLine(Encoding.UTF8.GetString(ms3.ToArray())); //abadkkg //从第4位替换掉了两个字节为KK
  78.  
     
  79.  
    Console.ReadKey();
  80.  
    }

接下来实现数据类的转换:

  1.  
    using System.IO;
  2.  
    using System.Runtime.Serialization;
  3.  
    using System.Runtime.Serialization.Formatters.Binary;
  4.  
     
  5.  
    public class DataSwitch
  6.  
    {
  7.  
     
  8.  
    /// <summary>
  9.  
    /// 数据类对象转成字节流
  10.  
    /// </summary>
  11.  
    /// <param name="obj"></param>
  12.  
    /// <returns></returns>
  13.  
    /// //MemoryStream: 创建其支持存储区为内存的流。
  14.  
    //IFormatter : 提供将序列化对象格式化的功能。
  15.  
    public static byte[] ObjectToBytes(object obj)
  16.  
    {
  17.  
    using (MemoryStream ms = new MemoryStream())
  18.  
    {
  19.  
    // //以二进制格式将对象或整个连接对象图形序列化和反序列化。
  20.  
    IFormatter formatter = new BinaryFormatter();
  21.  
    //把字符串以二进制放进memStream中
  22.  
    formatter.Serialize(ms, obj);
  23.  
    //返回从其创建此流的无符号字节数组。 是会返回所有分配的字节,不管用没用到。
  24.  
    ////返回无符号字节数组 ,无符号字节数组 其实就是byte(0~255),有符号字节sbyte(-128~127)
  25.  
    return ms.GetBuffer();
  26.  
    }
  27.  
    }
  28.  
     
  29.  
    /// <summary>
  30.  
    /// 字节流转成数据类对象
  31.  
    /// </summary>
  32.  
    /// <param name="bytes"></param>
  33.  
    /// <returns></returns>
  34.  
    public static object BytesToObject(byte[] bytes)
  35.  
    {
  36.  
    using (MemoryStream ms = new MemoryStream(bytes))
  37.  
    {
  38.  
    // //以二进制格式将对象或整个连接对象图形序列化和反序列化。
  39.  
    IFormatter formatter = new BinaryFormatter();
  40.  
    //把字符串以二进制放进memStream中
  41.  
    return formatter.Deserialize(ms);
  42.  
    }
  43.  
    }
  44.  
    }

原文地址1:http://www.cnblogs.com/kissdodog/archive/2013/01/20/2868864.html

原文地址2:https://blog.csdn.net/elineSea/article/details/71703552

C#中MemoryStream类的介绍的更多相关文章

  1. android中画图类的介绍Path

    Paint类相关属性: /** * Paint类介绍 * * Paint即画笔,在绘图过程中起到了极其重要的作用,画笔主要保存了颜色, * 样式等绘制信息,指定了如何绘制文本和图形,画笔对象有很多设置 ...

  2. Lazarus中TScreen类使用介绍

    描述:虚拟屏幕(桌面)可以包含多个物理显示器.Screen对象是鼠标指针.字体.窗体. 对于Delphi兼容的(不可见)DataModules也被列出了. 同时也追踪当前活动窗体窗体.控件和指针. S ...

  3. JavaScript中class类的介绍

    class的概念 一.我们为什么要用到class类? 因为通过class类来创建对象,使得开发者不必写重复的代码,以达到代码复用的目的.它基于的逻辑是,两个或多个对象的结构功能类似,可以抽象出一个模板 ...

  4. java中Runtime类详细介绍

    Runtime类描述了虚拟机一些信息.该类采用了单例设计模式,可以通过静态方法 getRuntime()获取Runtime类实例.下面演示了获取虚拟机的内存信息: package Main; publ ...

  5. Mybatis中实体类属性与数据库列表间映射方法介绍

               这篇文章主要介绍了Mybatis中实体类属性与数据列表间映射方法介绍,一共四种方法方法,供大家参考.         Mybatis不像Hibernate中那么自动化,通过@Co ...

  6. java中ReentrantLock类的详细介绍(详解)

    博主如果看到请联系小白,小白记不清地址了 简介 ReentrantLock是一个可重入且独占式的锁,它具有与使用synchronized监视器锁相同的基本行为和语义,但与synchronized关键字 ...

  7. opencv中mat类介绍

    The class Mat represents an n-dimensional dense numerical single-channel or multi-channel array. It ...

  8. java中Timer类的详细介绍(详解)

    一.概念 定时计划任务功能在Java中主要使用的就是Timer对象,它在内部使用多线程的方式进行处理,所以它和多线程技术还是有非常大的关联的.在JDK中Timer类主要负责计划任务的功能,也就是在指定 ...

  9. Objective-C中的类目,延展,协议

    Objective-C中的类目(Category),延展(Extension),协议(Protocol)这些名词看起来挺牛的,瞬间感觉OC好高大上.在其他OOP语言中就没见过这些名词,刚看到这三个名词 ...

随机推荐

  1. 大数据架构:搭建CDH5.5.1分布式集群环境

    yum install -y ntp gcc make lrzsz wget vim sysstat.x86_64 xinetd screen expect rsync bind-utils ioto ...

  2. spring gateway 截取response 长度缺失

    网上找到一段获取修改response的代码:https://blog.csdn.net/tianyaleixiaowu/article/details/83618037 代码如下: import or ...

  3. js 时间戳转时间工具类 js时间戳与时间互转

    /** * 时间戳格式化函数 * @param {string} format 格式 * @param {int} timestamp 要格式化的时间 默认为当前时间 * @return {strin ...

  4. 使用MegaCli监控Linux硬盘

    1.首先查看机器是否使用的是MegaRAID卡 dmesg | grep RAID [ 6.932741] scsi host0: Avago SAS based MegaRAID driver 2. ...

  5. shell脚本学习笔记(符号)

    shell脚本的学习: 1.Shell的作用是解释运行用户的命令,用户输入一条命令,Shell就解释运行一条,这样的方式称为交互式(Interactive),Shell还有 一种运行命令的方式称为批处 ...

  6. 更改了react-redux 官方网站的todolist结构

    最近在学习胡子大哈的react小书,内容讲的由浅入深,很值得react,react-redux小白一读. 废话不多说直接上地址:http://huziketang.mangojuice.top/boo ...

  7. Qt编写自定义控件8-动画按钮组控件

    前言 动画按钮组控件可以用来当做各种漂亮的导航条用,既可以设置成顶部底部+左侧右侧,还自带精美的滑动效果,还可以设置悬停滑动等各种颜色,原创作者雨田哥(QQ:3246214072),驰骋Qt控件界多年 ...

  8. AWS事故总结,几招教你规避风险

    版权声明:本文由王煜奕原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/90687001488360802 来源:腾云阁 ht ...

  9. 3D Object Classification With Point Convolution —— 点云卷积网络

    今天刚刚得到消息,之前投给IROS 2017的文章收录了.很久很久没有写过博客,今天正好借这个机会来谈谈点云卷积网络的一些细节. 1.点云与三维表达 三维数据后者说空间数据有很多种表达方式,比如:RG ...

  10. Centos下普通用户设置sudo权限

    若执行sudo命令的用户没有sodu权限,则会报以下错误 violet is not in the sudoers file.This incident will be reported 若想让vio ...