C# 内存流使用方法 C#如何使用MemoryStream

来源:这里教程网 时间:2026-02-21 17:42:41 作者:

MemoryStream 用来干啥?不是所有场景都适合

MemoryStream 是把内存当“文件”用的流,适合小到中等数据的临时读写——比如序列化对象、拼接字节数组、处理 HTTP 响应体、生成 Excel/PDF 内存流。它不持久、不线程安全(默认)、不自动释放资源,拿它读 GB 级文件或长期持有引用,容易触发

OutOfMemoryException
或内存泄漏。

常见误用:用

MemoryStream
缓存 Web API 的大文件响应后直接返回给前端(该用
FileStream
或流式传输);或在 ASP.NET Core 中把
MemoryStream
存进静态集合长期持有。

创建和写入 MemoryStream 的三种典型方式

关键点:是否预分配容量、是否允许扩展、写完要不要重置位置。

空构造函数
new MemoryStream()
:内部缓冲区动态增长,但频繁扩容有性能开销;写完要调
stream.Position = 0
才能读
带容量的构造函数
new MemoryStream(int capacity)
:预分配缓冲区,避免多次 realloc;容量只是初始值,仍可自动扩展
传入字节数组
new MemoryStream(byte[] buffer)
:创建的是“可读写视图”,修改会影响原数组;若只读,用
new MemoryStream(byte[], false)
防误写
byte[] data = Encoding.UTF8.GetBytes("hello");
using var stream = new MemoryStream(data, writable: false); // 只读视图
// stream.Write(...) 会抛 NotSupportedException

读取时 Position 和 GetBuffer 的坑

Position
是当前读/写偏移,
Length
是实际数据长度,
Capacity
是已分配缓冲区大小——三者常不相等。尤其注意
GetBuffer()
返回的是整个底层数组,不是有效数据部分。

读取全部内容推荐用
ToArray()
(安全、返回精确字节),不是
GetBuffer()
GetBuffer()
只在你明确需要复用缓冲区且知道
Length
边界时才用,否则可能读到脏数据
写入后没调
Position = 0
就读,会得到空结果(因为指针在末尾)
using var stream = new MemoryStream();
stream.Write(Encoding.UTF8.GetBytes("test"));
Console.WriteLine(stream.Length);     // 输出 4
Console.WriteLine(stream.GetBuffer().Length); // 可能是 256 或更大(内部扩容后的容量)
Console.WriteLine(stream.ToArray().Length);   // 稳定输出 4

配合 BinaryWriter / BinaryReader 或序列化使用

MemoryStream 经常作为二进制序列化的载体,但要注意编码一致性与生命周期管理。

BinaryWriter
写完别忘了
Flush()
(虽然
Dispose
也会刷,但显式更清晰)
反序列化时,确保
MemoryStream.Position == 0
,否则
BinaryReader
从中间开始读会失败
JSON.NET 或 System.Text.Json 序列化到
MemoryStream
时,记得用
Utf8JsonWriter
直接写入,避免中间转
string
造成额外 GC

真正容易被忽略的是:在异步方法里用

MemoryStream
,别把它传给多个并发任务共享操作——没有内置锁,
Position
竞态会导致读写错乱。

相关推荐