memorystream 用于将内存当作临时“文件”进行小到中等数据的读写操作,如序列化、http响应处理、生成excel/pdf等;不适用于大文件或长期缓存,因其不持久、非线程安全、需手动管理资源。

MemoryStream 用来干啥?不是所有场景都适合
MemoryStream 是把内存当“文件”用的流,适合小到中等数据的临时读写——比如序列化对象、拼接字节数组、处理 HTTP 响应体、生成 Excel/PDF 内存流。它不持久、不线程安全(默认)、不自动释放资源,拿它读 GB 级文件或长期持有引用,容易触发 OutOfMemoryException 或内存泄漏。
常见误用:用 MemoryStream 缓存 Web API 的大文件响应后直接返回给前端(该用 FileStream 或流式传输);或在 ASP.NET Core 中把 MemoryStream 存进静态集合长期持有。
创建和写入 MemoryStream 的三种典型方式
关键点:是否预分配容量、是否允许扩展、写完要不要重置位置。
95Shop可以免费下载使用,是一款仿醉品商城网店系统,内置SEO优化,具有模块丰富、管理简洁直观,操作易用等特点,系统功能完整,运行速度较快,采用ASP.NET(C#)技术开发,配合SQL Serve2000数据库存储数据,运行环境为微软ASP.NET 2.0。95Shop官方网站定期开发新功能和维护升级。可以放心使用! 安装运行方法 1、下载软件压缩包; 2、将下载的软件压缩包解压缩,得到we
- 空构造函数
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 竞态会导致读写错乱。








