• 【.Net实用方法总结】 整理并总结System.IO中MemoryStream类及其方法介绍


    🐋作者简介:博主是一位.Net开发者,同时也是RPA和低代码平台的践行者。
    🐬个人主页:会敲键盘的肘子
    🐰系列专栏:.Net实用方法总结
    🦀专栏简介:博主针对.Net开发和C站问答过程中遇到的问题进行总结,形成本专栏,希望可以帮助到您解决问题。
    🐶座右铭:总有一天你所坚持的会反过来拥抱你。


    在这里插入图片描述

    🌈写在前面:

    本文主要介绍System.IO命名空间的MemoryStream 类,介绍其常用的方法和示例说明。


    👉本文关键字:System.IO、MemoryStream类、内存流、方法示例、C#

    文章目录

    1️⃣ System.IO命名空间

    .NET中的IO操作命名空间,包含允许读写文件数据流的类型以及提供基本文件和目录支持的类型。

    我们在.NET中的IO操作,经常需要调用一下几个类。

    • FileStream类

    ​ 文件流类,负责大文件的拷贝,读写。

    • Path类

    ​ Path类中方法,基本都是对字符串(文件名)的操作,与实际文件没多大关系。

    • File类

      File类可以进行一些对小文件拷贝、剪切操作,还能读一些文档文件。

    • Dirctory类

      目录操作,创建文件、删除目录,获取目录下文件名等等。

    2️⃣ MemoryStream类

    ♈ 定义

    创建一个流,其后备存储为内存。

    public class MemoryStream : System.IO.Stream
    
    • 1
    ♉ 示例

    下面的代码示例演示如何使用内存作为后盾存储来读取和写入数据。

    using System;
    using System.IO;
    using System.Text;
    
    class MemStream
    {
        static void Main()
        {
            int count;
            byte[] byteArray;
            char[] charArray;
            UnicodeEncoding uniEncoding = new UnicodeEncoding();
    
            // Create the data to write to the stream.
            byte[] firstString = uniEncoding.GetBytes(
                "Invalid file path characters are: ");
            byte[] secondString = uniEncoding.GetBytes(
                Path.GetInvalidPathChars());
    
            using(MemoryStream memStream = new MemoryStream(100))
            {
                // Write the first string to the stream.
                memStream.Write(firstString, 0 , firstString.Length);
    
                // Write the second string to the stream, byte by byte.
                count = 0;
                while(count < secondString.Length)
                {
                    memStream.WriteByte(secondString[count++]);
                }
    
                // Write the stream properties to the console.
                Console.WriteLine(
                    "Capacity = {0}, Length = {1}, Position = {2}\n",
                    memStream.Capacity.ToString(),
                    memStream.Length.ToString(),
                    memStream.Position.ToString());
    
                // Set the position to the beginning of the stream.
                memStream.Seek(0, SeekOrigin.Begin);
    
                // Read the first 20 bytes from the stream.
                byteArray = new byte[memStream.Length];
                count = memStream.Read(byteArray, 0, 20);
    
                // Read the remaining bytes, byte by byte.
                while(count < memStream.Length)
                {
                    byteArray[count++] = (byte)memStream.ReadByte();
                }
    
                // Decode the byte array into a char array
                // and write it to the console.
                charArray = new char[uniEncoding.GetCharCount(
                    byteArray, 0, count)];
                uniEncoding.GetDecoder().GetChars(
                    byteArray, 0, count, charArray, 0);
                Console.WriteLine(charArray);
            }
        }
    }
    
    • 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

    此类型可实现 IDisposable 接口,但实际上没有任何要释放的资源。 这意味着无需通过直接调用 Dispose() 或使用语言构造(C# 中的 using 或 Visual Basic 中的 Using)对其进行处理。

    MemoryStream如果将对象添加到 ResX 文件或 .resources 文件,请在运行时调用GetStream该方法以检索它。

    MemoryStream如果对象序列化为资源文件,则实际上将序列化为一个UnmanagedMemoryStream对象。 此行为可提供更好的性能,并能够直接获取指向数据的指针,而无需通过 Stream 方法。

    ♉ 构造函数

    初始化 MemoryStream 类的新实例

    MemoryStream()
    public MemoryStream ();
    
    • 1

    CanSeek属性CanReadCanWrite属性都设置为 true

    使用 SetLength 该方法将长度设置为大于当前流的容量的值时,当前流的容量会自动增加。

    此构造函数公开返回的基础流 GetBuffer

    MemoryStream(Byte[])

    基于指定的字节数组初始化 MemoryStream 类的无法调整大小的新实例。

    public MemoryStream (byte[] buffer);
    
    • 1

    参数

    buffer

    Byte[]

    从中创建当前流的无符号字节数组。

    CanSeek属性CanReadCanWrite属性都设置为 trueCapacity 设置为指定字节数组的长度。 可将新流写入,但不可调整大小。

    流的长度不能设置为大于指定字节数组的初始长度的值;但是, (可以看到 SetLength) 截断流。

    MemoryStream(Int32)

    使用按指定要求初始化的可扩展容量初始化 MemoryStream 类的新实例。

    public MemoryStream (int capacity);
    
    • 1

    参数

    capacity

    Int32

    内部数组的初始大小(以字节为单位)。

    示例

    此代码示例是为 MemoryStream 类提供的一个更大示例的一部分。

    using(MemoryStream memStream = new MemoryStream(100))
    
    • 1
    MemoryStream(Byte[], Boolean)

    CanWrite 属性按指定设置的状态下,基于指定的字节数组初始化 MemoryStream 类的无法调整大小的新实例。

    public MemoryStream (byte[] buffer, bool writable);
    
    • 1

    参数

    buffer

    Byte[]

    内部数组的初始大小(以字节为单位)。

    writable

    bool

    CanWrite 属性的设置,确定该流是否支持写入。

    MemoryStream(Byte[], Int32, Int32)

    基于字节数组的指定区域(索引)初始化 MemoryStream 类的无法调整大小的新实例。

    public MemoryStream (byte[] buffer, int index, int count);
    
    • 1

    参数

    buffer

    Byte[]

    内部数组的初始大小(以字节为单位)。

    index

    Int

    buffer 内的索引,流从此处开始。

    count

    Int

    流的长度(以字节为单位)。

    ♊ 属性
    CanRead 当在派生类中重写时,获取指示当前流是否支持读取的值
    public override bool CanRead { get; }
    
    • 1
    CanSeek 获取一个值,该值指示当前流是否支持查找
    public override bool CanSeek { get; }
    
    • 1
    CanWrite 获取一个值,该值指示当前流是否支持写入
    public override bool CanWrite { get; }
    
    • 1
    Capacity 获取或设置分配给该流的字节数
    public virtual int Capacity { get; set; }
    
    • 1

    示例

    // Write the stream properties to the console.
    Console.WriteLine(
        "Capacity = {0}, Length = {1}, Position = {2}\n",
        memStream.Capacity.ToString(),
        memStream.Length.ToString(),
        memStream.Position.ToString());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Capacity 是系统提供的字节数组的缓冲区长度。 Capacity 不能设置为小于流当前长度的值。

    Length 当在派生类中重写时,获取流长度(以字节为单位)
    public override long Length { get; }
    
    • 1
    ♌ 常用方法
    BeginRead(Byte[], Int32, Int32, AsyncCallback, Object) 开始异步读操作
    public override IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback? callback, object? state);
    
    • 1

    参数

    buffer

    Byte[]

    数据读入的缓冲区。

    offset

    Int32

    buffer 中的字节偏移量,从该偏移量开始写入从内存流中读取的数据。

    count

    Int32

    最多读取的字节数。

    callback

    [AsyncCallback](https://docs.microsoft.com/zh-cn/dotnet/api/system.int32?view=net-6.0)

    可选的异步回调,在完成读取时调用。

    state

    Object

    一个用户提供的对象,它将该特定的异步读取请求与其他请求区别开来。

    返回

    [IAsyncResult](https://docs.microsoft.com/zh-cn/dotnet/api/system.int32?view=net-6.0)

    表示异步读取的 IAsyncResult(可能仍处于挂起状态)。

    BeginWrite(Byte[], Int32, Int32, AsyncCallback, Object) 开始异步写操作
    public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback? callback, object? state);
    
    • 1

    参数

    buffer

    Byte[]

    从中写入数据的缓冲区。

    offset

    Int32

    buffer 中的字节偏移量,从此处开始写入。

    count

    Int32

    最多写入的字节数。

    callback

    [AsyncCallback](https://docs.microsoft.com/zh-cn/dotnet/api/system.int32?view=net-6.0)

    可选的异步回调,在完成写入时调用。

    state

    Object

    一个用户提供的对象,它将该特定的异步写入请求与其他请求区别开来。

    返回

    [IAsyncResult](https://docs.microsoft.com/zh-cn/dotnet/api/system.int32?view=net-6.0)

    表示异步写入的 IAsyncResult(可能仍处于挂起状态)。

    CopyTo(Stream, Int32) 使用指定的缓冲区大小,从当前内存流中读取字节并将其写入到另一流中
    public override void CopyTo (System.IO.Stream destination, int bufferSize);
    
    • 1

    参数

    destination

    Stream

    当前流的内容将复制到的流。

    bufferSize

    Int32

    缓冲区的大小。 此值必须大于零。 默认大小为 81920。

    CopyToAsync(Stream, Int32, CancellationToken) 使用指定的缓冲区大小和取消令牌,从当前流中异步读取所有字节并将其写入到另一个流中
    public override System.Threading.Tasks.Task CopyToAsync (System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken);
    
    • 1

    参数

    destination

    Stream

    当前流的内容将复制到的流。

    bufferSize

    Int32

    缓冲区的大小。 此值必须大于零。 默认大小为 81920。

    cancellationToken

    CancellationToken

    要监视取消请求的标记。

    返回

    Task

    表示异步复制操作的任务。

    Dispose(Boolean) 释放 MemoryStream 类使用的非托管资源,并可以选择释放托管资源
    protected override void Dispose (bool disposing);
    
    • 1
    GetBuffer() 返回从中创建此流的无符号字节的数组
    public virtual byte[] GetBuffer ();
    
    • 1
    Read(Byte[], Int32, Int32) 从当前流中读取字节块并将数据写入缓冲区
    public override int Read (byte[] buffer, int offset, int count);
    
    • 1

    参数

    buffer

    Byte[]

    当此方法返回时,包含指定的字节数组,此数组中 offset 和 (offset + count - 1) 之间的值被从当前流中读取的字符所替换。

    offset

    Int32

    buffer 中的从零开始的字节偏移量,从此处开始存储当前流中的数据。

    count

    Int32

    最多读取的字节数。

    返回

    Int32

    写入缓冲区中的总字节数。 如果字节数当前不可用,则总字节数可能小于所请求的字节数;如果在读取到任何字节前已到达流结尾,则为零。

    示例

    此代码示例是为 MemoryStream 类提供的一个更大示例的一部分。

    // Read the first 20 bytes from the stream.
    byteArray = new byte[memStream.Length];
    count = memStream.Read(byteArray, 0, 20);
    
    • 1
    • 2
    • 3

    offset 参数提供从当前流写入到的第一个字节 buffer 的偏移量。 该 count 参数提供从当前流读取的最大字节数。 返回的值是读取的实际字节数,如果到达流的末尾,则为零。

    如果读取操作成功,则流中的当前位置会按读取的字节数向前推进。 如果发生异常,流中的当前位置保持不变。

    Read仅当到达流的末尾时,该方法才会返回零。 在所有其他情况下, Read 始终在返回之前从流中读取至少一个字节。 根据定义,如果在调用 Read时流中没有可用数据,则 Read 该方法返回零, (自动) 到达流的末尾。 即使尚未到达流的末尾,实现也可以返回比请求的字节少。

    如果参数中指定的 buffer 字节数组是方法返回 GetBuffer 的基础缓冲区,则会覆盖数组内容,并且不会引发异常。

    ReadAsync(Byte[], Int32, Int32,CancellationToken) 从当前流异步读取字节的序列,将流中的位置提升读取的字节数,并监视取消请求
    public override System.Threading.Tasks.Task ReadAsync (byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken);
    
    • 1

    参数

    buffer

    Byte[]

    要写入数据的缓冲区。

    offset

    Int32

    buffer 中的字节偏移量,从该偏移量开始写入从流中读取的数据。

    count

    Int32

    最多读取的字节数。

    cancellationToken

    CancellationToken

    要监视取消请求的标记。 默认值是 None

    返回

    Task<Int32>

    表示异步读取操作的任务。 TResult 参数的值包含读入缓冲区的总字节数。 如果当前可用字节数少于所请求的字节数,则该结果值可小于所请求的字节数;如果已到达流结尾时,则为 0(零)。

    ReadByte() 从当前流中读取一个字节
    public override int ReadByte ();
    
    • 1

    返回

    Int32

    强制转换为 Int32 的字节;或者如果已到达流的末尾,则为 -1。

    示例

    此代码示例是为 MemoryStream 类提供的一个更大示例的一部分。

    // Read the remaining bytes, byte by byte.
    while(count < memStream.Length)
    {
        byteArray[count++] = (byte)memStream.ReadByte();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    Write(Byte[], Int32, Int32) 使用从缓冲区读取的数据将字节块写入当前流
    public override void Write (byte[] buffer, int offset, int count);
    
    • 1

    参数

    buffer

    Byte[]

    字节数组。 此方法将 count 个字节从 buffer 复制到当前流。

    offset

    Int32

    buffer 中的从零开始的字节偏移量,从此处开始将字节复制到当前流。

    count

    Int32

    要写入当前流的字节数。

    示例

    // Write the first string to the stream.
    memStream.Write(firstString, 0 , firstString.Length);
    
    • 1
    • 2

    使用 CanWrite 属性确定当前实例是否支持写入。 使用 WriteAsync 方法异步写入当前流。

    如果写入操作成功,则流中的位置将按写入的字节数前进。 如果发生异常,则流中的位置保持不变。

    WriteAsync(Byte[], Int32, Int32, CancellationToken) 将字节序列异步写入当前流,并将流的当前位置提升写入的字节数
    public override System.Threading.Tasks.Task WriteAsync (byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken);
    
    • 1

    参数

    buffer

    Byte[]

    从中写入数据的缓冲区。

    offset

    Int32

    buffer 中的从零开始的字节偏移量,从此处开始将字节复制到该流。

    count

    Int32

    最多写入的字节数。

    cancellationToken

    CancellationToken

    要监视取消请求的标记。 默认值是 None

    返回

    Task

    表示异步写入操作的任务。

    WriteByte(Byte) 一个字节写入文件流中的当前位置
    public override void WriteByte (byte value);
    
    • 1

    参数

    value

    Byte

    要写入流的字节。

    示例

    此代码示例是为 MemoryStream 类提供的一个更大示例的一部分。

    // Write the second string to the stream, byte by byte.
    count = 0;
    while(count < secondString.Length)
    {
        memStream.WriteByte(secondString[count++]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    WriteTo(Stream) 将此内存流的整个内容写入到另一个流中
    public virtual void WriteTo (System.IO.Stream stream);
    
    • 1

    参数

    stream

    Stream

    要写入此内存流的流。

    Flush() 清除此流的缓冲区,使得所有缓冲数据都写入到文件中
    public override void Flush ();
    
    • 1
    SetLength(Int64) 将当前流的长度设为指定值
    public override void SetLength (long value);
    
    • 1

    参数

    value

    Int64

    用于设置长度的值。

    如果指定的值小于流的当前长度,则会截断该流。 如果在截断流中的当前位置超过流的末尾,该方法将返回 -1,ReadByte该方法Read将零字节读取到提供的字节数组中,并且WriteWriteByte方法将指定字节追加到流末尾,增加其长度。 如果指定的值大于当前容量,并且该流可调整大小,则容量将增加,并且流中的当前位置保持不变。 如果长度增加,则旧长度和新长度之间的流内容将初始化为零。

    Seek(Int64, SeekOrigin) 将当前流中的位置设置为指定值
    public override long Seek (long offset, System.IO.SeekOrigin loc);
    
    • 1

    参数

    offset

    Int64

    流内的新位置。 它是相对于 loc 参数的位置,而且可正可负。

    loc

    SeekOrigin

    类型 SeekOrigin 的值,它用作查找引用点。

    返回

    Int64

    流内的新位置,通过将初始引用点和偏移量合并计算而得。

    示例

    // Set the position to the beginning of the stream.
    memStream.Seek(0, SeekOrigin.Begin);
    
    • 1
    • 2

    支持查找超出流长度的任何位置。

    如果不使用 Seek 该方法来确定流中的新位置(如果使用 MemoryStream 非零偏移量初始化)。 如果这样做, Seek 将返回不准确的值。 请改用该 Position 属性获取流的新位置。

    ♎ 更多方法

    更多方法请查阅官方文档MemoryStream类


    ⭐写在结尾:

    文章中出现的任何错误请大家批评指出,一定及时修改。

    希望写在这里的小伙伴能给个三连支持

  • 相关阅读:
    【Mysql】 InnoDB引擎深入 - 数据页 | 聚集索引
    基于树莓派的安保巡逻机器人--(一、快速人脸录入与精准人脸识别)
    LuatOS-SOC接口文档(air780E)--libcoap - coap数据处理
    详解设计模式:组合模式
    Vue中如何进行分布式搜索与全文搜索(如Elasticsearch)
    关于后台列表,跳转详情和编辑页面
    OPC是通讯协议吗&安全性
    万界星空科技/生产制造执行MES系统/开源MES/免费MES
    【C语言】递归问题(爬楼梯)
    面试问题梳理:项目中防止配置中的密码泄露-Jasypt
  • 原文地址:https://blog.csdn.net/baidu_33146219/article/details/126715895