C# MemoryStream中ToArray和GetBuffer的区别小小结
目录
- 前言
- 一、核心区别
- 二、具体示例
- 1.GetBuffer()的示例
- 2.ToArray()的示例
- 三、关键场景对比
- 四、注意事项
- 1. 异常情况
- 2. 容量与长度
- 3. 性能权衡
- 五、使用建议
前言
MemoryStream
中的 GetBuffer()
和 ToArray()
是两个用于获取流数据的方法,但它们的核心区别在于 数据范围、内存占用和安全性。
一、核心区别
特性 | GetBuffer() | ToArray() |
---|---|---|
返回内容 | 返回 底层缓冲区的完整数组(包含未使用的空间)。 | 返回 仅包含有效数据的数组(排除未使用的空间)。 |
内存占用 | 可能包含大量未使用的空字节(0 填充),占用更多内存。 | 仅包含实际写入的数据,内存更高效。 |
性能 | 速度快(直接返回引用,无需复制)。 | 速度较慢(需复制数据到新数组)。 |
安全性 | 可能暴露未初始化的字节(0 填充),可能导致数据污染或解析错误。 | 仅返回有效数据,避免未初始化字节的干扰。 |
二、具体示例
1.GetBuffer()的示例
public class Program { public static void Main(string[] args) { using (MemoryStream ms = new MemoryStream()) { byte[] data = Encoding.UTF8.GetBytes("test"); ms.Write(data, 0, data.Length); byte[] buffer = ms.GetBuffer(); // 返回长度为 256 的数组(默认初始容量为 256) Console.WriteLine(buffer.Length); // 输出:256 Console.WriteLine(ms.Length); // 输出:4(实际数据长度) Console.WriteLine(BitConverter.ToString(buffer)); // 输出:74-65-73-74-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-编程00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 } } }
- 问题:
- 返回的数组包含大量未使用的
0
填充字节(如示例中的256 - 4 = 252
个0
)。 - 如果直接使用
buffer
,可能导致数据解析错误(例如,将0
误认为有效数据)。
- 返回的数组包含大量未使用的
2.ToArray()的示例
public class Program { public static void Main(string[] args) { using (MemoryStream ms = new MemoryStream()) { byte[] data = Encoding.UTF8.GetBytes("test"); ms.Write(data, 0, data.Length); byte[] bytes = ms.ToArray(); // 返回长度为 4 的数组 Console.WriteLine(bytesEnMyLxXE.Length); // 输出:4 Console.WriteLine(ms.Length); // 输出:4(实际数据长度) Console.WriteLine(BitConverter.ToString(bytes));//输出:74-65-73-74 } } }
- 优势:
- 仅返回实际写入的数据(
Length
指定的范围),无多余0
填充。 - 更适合需要精确数据的场景(如序列化、加密、文件传输)。
- 仅返回实际写入的数据(
三、关键场景对比
场景 | 推荐方法 | 原因 |
---|---|---|
需要高效访问底层缓冲区(如直接操作内存) | GetBuffer() | 避免复制开销,但需确保仅使用有效数据范围。 |
需要精确数据(如网络传输、文件保存) | ToArray() | 确保数据不含未使用的 0,避免解析错误(如 Excel 文件损坏问题)。 |
流的容量远大于实际数据 | ToArray() | 避免浪费内存(如示例中 256 字节 vs 4 字节)。 |
需要避免未初始化字节的干扰 | ToArray() | 仅返回有效数据,安全性更高。 |
四、注意事项
1. 异常情况
GetBuffer()
的限制:- 如果
MemoryStream
是通过MemoryStream(byte[] buffer, bool writable)
构造函数创建,并且publiclyVisible
参数未设置为true
,则调用GetBuffer()
会抛出UnauthorizedAccessException
。 - 解决方案:改用
ToArray()
或确保构造时允许公开访问缓冲区。
- 如果
2. 容量与长度
Capacity
vsLength
:Capacity
是底层缓冲区的总大小(如默认256
)。Length
是实际写入数据的大小(如4
)。GetBuffer()
返回的数组长度等于Capacity
,而ToArray()
返回的数组长度等于Length
。
3. 性能权衡
- 大数据场景:
- 如果需要频繁操作大容量数据,可先通过
GetBuffer()
直接操作内存,但需严格控制访问范围(如Length
内)。
- 如果需要频繁操作大容量数据,可先通过
- 小数据或精确性优先:
- 直接使用
ToArray()
,避免未初始化字节的干扰。
- 直接使用
五、使用建议
- 优先使用
ToArray()
,除非明确需要直接操作底层缓冲区且能确保安全。 - 在涉及文件导出、网络传输或第三方库解析时,
ToArray()
更可http://www.devze.com靠(如解决 Excel 文件损坏问题)。 - 通过
TryGetBuffer()
替代GetBuffer()
,避免异常风险。- .NET 4.5+ 引入了
TryGetBuffer()
方法,可安全检查是否允许获取缓冲区:
usinandroidg (MemoryStream ms = new MemoryStream()) { if (ms.TryGetBuffer(out var buffer)) { // 安全获取缓冲区 byte[] data = new byte[ms.Length]; Array.Copy(buffer.Array, buffer.Offset, data, 0, (int)ms.Length); } else { // 使用 ToArray() byte[]http://www.devze.com data = ms.ToArray(); } }
- .NET 4.5+ 引入了
到此这篇关于C# MemoryStream 中 ToArray 和 GetBuffer 的区别的文章就介绍到这了,更多相关C# ToArray GetBuffer内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论