作者简介:博主是一位.Net开发者,同时也是RPA和低代码平台的践行者。
个人主页:会敲键盘的肘子
系列专栏:.Net实用方法总结
专栏简介:博主针对.Net开发和C站问答过程中遇到的问题进行总结,形成本专栏,希望可以帮助到您解决问题。
座右铭:总有一天你所坚持的会反过来拥抱你。
写在前面:
本文主要介绍System.IO命名空间的MemoryStream 类,介绍其常用的方法和示例说明。
本文关键字:System.IO、MemoryStream类、内存流、方法示例、C#
.NET中的IO操作命名空间,包含允许读写文件和数据流的类型以及提供基本文件和目录支持的类型。
我们在.NET中的IO操作,经常需要调用一下几个类。
文件流类,负责大文件的拷贝,读写。
Path类中方法,基本都是对字符串(文件名)的操作,与实际文件没多大关系。
File类
File类可以进行一些对小文件拷贝、剪切操作,还能读一些文档文件。
Dirctory类
目录操作,创建文件、删除目录,获取目录下文件名等等。
创建一个流,其后备存储为内存。
public class MemoryStream : System.IO.Stream
下面的代码示例演示如何使用内存作为后盾存储来读取和写入数据。
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);
}
}
}
此类型可实现 IDisposable 接口,但实际上没有任何要释放的资源。 这意味着无需通过直接调用 Dispose() 或使用语言构造(C# 中的
using
或 Visual Basic 中的Using
)对其进行处理。MemoryStream如果将对象添加到 ResX 文件或 .resources 文件,请在运行时调用GetStream该方法以检索它。
MemoryStream如果对象序列化为资源文件,则实际上将序列化为一个UnmanagedMemoryStream对象。 此行为可提供更好的性能,并能够直接获取指向数据的指针,而无需通过 Stream 方法。
初始化 MemoryStream 类的新实例
public MemoryStream ();
CanSeek属性CanRead和CanWrite属性都设置为
true
。使用 SetLength 该方法将长度设置为大于当前流的容量的值时,当前流的容量会自动增加。
此构造函数公开返回的基础流 GetBuffer 。
基于指定的字节数组初始化 MemoryStream 类的无法调整大小的新实例。
public MemoryStream (byte[] buffer);
参数
buffer
Byte[]
从中创建当前流的无符号字节数组。
CanSeek属性CanRead和CanWrite属性都设置为
true
。 Capacity 设置为指定字节数组的长度。 可将新流写入,但不可调整大小。流的长度不能设置为大于指定字节数组的初始长度的值;但是, (可以看到 SetLength) 截断流。
使用按指定要求初始化的可扩展容量初始化 MemoryStream 类的新实例。
public MemoryStream (int capacity);
参数
capacity
Int32
内部数组的初始大小(以字节为单位)。
示例
此代码示例是为 MemoryStream 类提供的一个更大示例的一部分。
using(MemoryStream memStream = new MemoryStream(100))
在 CanWrite 属性按指定设置的状态下,基于指定的字节数组初始化 MemoryStream 类的无法调整大小的新实例。
public MemoryStream (byte[] buffer, bool writable);
参数
buffer
Byte[]
内部数组的初始大小(以字节为单位)。
writable
bool
CanWrite 属性的设置,确定该流是否支持写入。
基于字节数组的指定区域(索引)初始化 MemoryStream 类的无法调整大小的新实例。
public MemoryStream (byte[] buffer, int index, int count);
参数
buffer
Byte[]
内部数组的初始大小(以字节为单位)。
index
Int
buffer
内的索引,流从此处开始。
count
Int
流的长度(以字节为单位)。
public override bool CanRead { get; }
public override bool CanSeek { get; }
public override bool CanWrite { get; }
public virtual int Capacity { get; set; }
示例
// 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());
Capacity
是系统提供的字节数组的缓冲区长度。Capacity
不能设置为小于流当前长度的值。
public override long Length { get; }
public override IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback? callback, object? state);
参数
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(可能仍处于挂起状态)。
public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback? callback, object? state);
参数
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
(可能仍处于挂起状态)。
public override void CopyTo (System.IO.Stream destination, int bufferSize);
参数
destination
Stream
当前流的内容将复制到的流。
bufferSize
Int32
缓冲区的大小。 此值必须大于零。 默认大小为 81920。
public override System.Threading.Tasks.Task CopyToAsync (System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken);
参数
destination
Stream
当前流的内容将复制到的流。
bufferSize
Int32
缓冲区的大小。 此值必须大于零。 默认大小为 81920。
cancellationToken
CancellationToken
要监视取消请求的标记。
返回
Task
表示异步复制操作的任务。
protected override void Dispose (bool disposing);
public virtual byte[] GetBuffer ();
public override int Read (byte[] buffer, int offset, int count);
参数
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);
该
offset
参数提供从当前流写入到的第一个字节buffer
的偏移量。 该count
参数提供从当前流读取的最大字节数。 返回的值是读取的实际字节数,如果到达流的末尾,则为零。如果读取操作成功,则流中的当前位置会按读取的字节数向前推进。 如果发生异常,流中的当前位置保持不变。
Read
仅当到达流的末尾时,该方法才会返回零。 在所有其他情况下,Read
始终在返回之前从流中读取至少一个字节。 根据定义,如果在调用Read
时流中没有可用数据,则Read
该方法返回零, (自动) 到达流的末尾。 即使尚未到达流的末尾,实现也可以返回比请求的字节少。如果参数中指定的
buffer
字节数组是方法返回 GetBuffer 的基础缓冲区,则会覆盖数组内容,并且不会引发异常。
public override System.Threading.Tasks.Task ReadAsync (byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken);
参数
buffer
Byte[]
要写入数据的缓冲区。
offset
Int32
buffer
中的字节偏移量,从该偏移量开始写入从流中读取的数据。
count
Int32
最多读取的字节数。
cancellationToken
CancellationToken
要监视取消请求的标记。 默认值是 None。
返回
Task
表示异步读取操作的任务。
TResult
参数的值包含读入缓冲区的总字节数。 如果当前可用字节数少于所请求的字节数,则该结果值可小于所请求的字节数;如果已到达流结尾时,则为 0(零)。
public override int ReadByte ();
返回
Int32
强制转换为 Int32 的字节;或者如果已到达流的末尾,则为 -1。
示例
此代码示例是为 MemoryStream 类提供的一个更大示例的一部分。
// Read the remaining bytes, byte by byte.
while(count < memStream.Length)
{
byteArray[count++] = (byte)memStream.ReadByte();
}
public override void Write (byte[] buffer, int offset, int count);
参数
buffer
Byte[]
字节数组。 此方法将
count
个字节从buffer
复制到当前流。
offset
Int32
buffer
中的从零开始的字节偏移量,从此处开始将字节复制到当前流。
count
Int32
要写入当前流的字节数。
示例
// Write the first string to the stream.
memStream.Write(firstString, 0 , firstString.Length);
使用 CanWrite 属性确定当前实例是否支持写入。 使用 WriteAsync 方法异步写入当前流。
如果写入操作成功,则流中的位置将按写入的字节数前进。 如果发生异常,则流中的位置保持不变。
public override System.Threading.Tasks.Task WriteAsync (byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken);
参数
buffer
Byte[]
从中写入数据的缓冲区。
offset
Int32
buffer
中的从零开始的字节偏移量,从此处开始将字节复制到该流。
count
Int32
最多写入的字节数。
cancellationToken
CancellationToken
要监视取消请求的标记。 默认值是 None。
返回
Task
表示异步写入操作的任务。
public override void WriteByte (byte value);
参数
value
Byte
要写入流的字节。
示例
此代码示例是为 MemoryStream 类提供的一个更大示例的一部分。
// Write the second string to the stream, byte by byte.
count = 0;
while(count < secondString.Length)
{
memStream.WriteByte(secondString[count++]);
}
public virtual void WriteTo (System.IO.Stream stream);
参数
stream
Stream
要写入此内存流的流。
public override void Flush ();
public override void SetLength (long value);
参数
value
Int64
用于设置长度的值。
如果指定的值小于流的当前长度,则会截断该流。 如果在截断流中的当前位置超过流的末尾,该方法将返回 -1,ReadByte该方法Read将零字节读取到提供的字节数组中,并且WriteWriteByte方法将指定字节追加到流末尾,增加其长度。 如果指定的值大于当前容量,并且该流可调整大小,则容量将增加,并且流中的当前位置保持不变。 如果长度增加,则旧长度和新长度之间的流内容将初始化为零。
public override long Seek (long offset, System.IO.SeekOrigin loc);
参数
offset
Int64
流内的新位置。 它是相对于
loc
参数的位置,而且可正可负。
loc
SeekOrigin
类型 SeekOrigin 的值,它用作查找引用点。
返回
Int64
流内的新位置,通过将初始引用点和偏移量合并计算而得。
示例
// Set the position to the beginning of the stream.
memStream.Seek(0, SeekOrigin.Begin);
支持查找超出流长度的任何位置。
如果不使用 Seek 该方法来确定流中的新位置(如果使用 MemoryStream 非零偏移量初始化)。 如果这样做, Seek 将返回不准确的值。 请改用该 Position 属性获取流的新位置。
更多方法请查阅官方文档MemoryStream类。
⭐写在结尾:
文章中出现的任何错误请大家批评指出,一定及时修改。
希望写在这里的小伙伴能给个三连支持!