C#?MemoryStream中ToArray和GetBuffer的區(qū)別小小結(jié)
更新時間:2025年07月31日 10:11:41 作者:鯉籽鯤
MemoryStream?中的?GetBuffer()?和?ToArray()?是兩個用于獲取流數(shù)據(jù)的方法,核心區(qū)別在于數(shù)據(jù)范圍、內(nèi)存占用和安全性,本文就來介紹一下兩者的區(qū)別,感興趣的額可以了解一下
前言
MemoryStream 中的 GetBuffer() 和 ToArray() 是兩個用于獲取流數(shù)據(jù)的方法,但它們的核心區(qū)別在于 數(shù)據(jù)范圍、內(nèi)存占用和安全性。
一、核心區(qū)別
| 特性 | GetBuffer() | ToArray() |
|---|---|---|
| 返回內(nèi)容 | 返回 底層緩沖區(qū)的完整數(shù)組 (包含未使用的空間)。 | 返回 僅包含有效數(shù)據(jù)的數(shù)組 (排除未使用的空間)。 |
| 內(nèi)存占用 | 可能包含大量未使用的空字節(jié)(0 填充), 占用更多內(nèi)存。 | 僅包含實際寫入的數(shù)據(jù), 內(nèi)存更高效。 |
| 性能 | 速度快(直接返回引用,無需復(fù)制)。 | 速度較慢(需復(fù)制數(shù)據(jù)到新數(shù)組)。 |
| 安全性 | 可能暴露未初始化的字節(jié)(0 填充), 可能導(dǎo)致數(shù)據(jù)污染或解析錯誤。 | 僅返回有效數(shù)據(jù), 避免未初始化字節(jié)的干擾。 |
二、具體示例
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 的數(shù)組(默認(rèn)初始容量為 256)
Console.WriteLine(buffer.Length); // 輸出:256
Console.WriteLine(ms.Length); // 輸出:4(實際數(shù)據(jù)長度)
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
}
}
}
- 問題:
- 返回的數(shù)組包含大量未使用的
0填充字節(jié)(如示例中的256 - 4 = 252個0)。 - 如果直接使用
buffer,可能導(dǎo)致數(shù)據(jù)解析錯誤(例如,將0誤認(rèn)為有效數(shù)據(jù))。
- 返回的數(shù)組包含大量未使用的
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 的數(shù)組
Console.WriteLine(bytes.Length); // 輸出:4
Console.WriteLine(ms.Length); // 輸出:4(實際數(shù)據(jù)長度)
Console.WriteLine(BitConverter.ToString(bytes));//輸出:74-65-73-74
}
}
}
- 優(yōu)勢:
- 僅返回實際寫入的數(shù)據(jù)(
Length指定的范圍),無多余0填充。 - 更適合需要精確數(shù)據(jù)的場景(如序列化、加密、文件傳輸)。
- 僅返回實際寫入的數(shù)據(jù)(
三、關(guān)鍵場景對比
| 場景 | 推薦方法 | 原因 |
|---|---|---|
| 需要高效訪問底層緩沖區(qū)(如直接操作內(nèi)存) | GetBuffer() | 避免復(fù)制開銷,但需確保僅使用有效數(shù)據(jù)范圍。 |
| 需要精確數(shù)據(jù)(如網(wǎng)絡(luò)傳輸、文件保存) | ToArray() | 確保數(shù)據(jù)不含未使用的 0,避免解析錯誤(如 Excel 文件損壞問題)。 |
| 流的容量遠(yuǎn)大于實際數(shù)據(jù) | ToArray() | 避免浪費內(nèi)存(如示例中 256 字節(jié) vs 4 字節(jié))。 |
| 需要避免未初始化字節(jié)的干擾 | ToArray() | 僅返回有效數(shù)據(jù),安全性更高。 |
四、注意事項
1. 異常情況
GetBuffer()的限制:- 如果
MemoryStream是通過MemoryStream(byte[] buffer, bool writable)構(gòu)造函數(shù)創(chuàng)建,并且publiclyVisible參數(shù)未設(shè)置為true,則調(diào)用GetBuffer()會拋出UnauthorizedAccessException。 - 解決方案:改用
ToArray()或確保構(gòu)造時允許公開訪問緩沖區(qū)。
- 如果
2. 容量與長度
CapacityvsLength:Capacity是底層緩沖區(qū)的總大?。ㄈ缒J(rèn)256)。Length是實際寫入數(shù)據(jù)的大?。ㄈ?4)。GetBuffer()返回的數(shù)組長度等于Capacity,而ToArray()返回的數(shù)組長度等于Length。
3. 性能權(quán)衡
- 大數(shù)據(jù)場景:
- 如果需要頻繁操作大容量數(shù)據(jù),可先通過
GetBuffer()直接操作內(nèi)存,但需嚴(yán)格控制訪問范圍(如Length內(nèi))。
- 如果需要頻繁操作大容量數(shù)據(jù),可先通過
- 小數(shù)據(jù)或精確性優(yōu)先:
- 直接使用
ToArray(),避免未初始化字節(jié)的干擾。
- 直接使用
五、使用建議
- 優(yōu)先使用
ToArray(),除非明確需要直接操作底層緩沖區(qū)且能確保安全。 - 在涉及文件導(dǎo)出、網(wǎng)絡(luò)傳輸或第三方庫解析時,
ToArray()更可靠(如解決 Excel 文件損壞問題)。 - 通過
TryGetBuffer()替代GetBuffer(),避免異常風(fēng)險。- .NET 4.5+ 引入了
TryGetBuffer()方法,可安全檢查是否允許獲取緩沖區(qū):
using (MemoryStream ms = new MemoryStream()) { if (ms.TryGetBuffer(out var buffer)) { // 安全獲取緩沖區(qū) byte[] data = new byte[ms.Length]; Array.Copy(buffer.Array, buffer.Offset, data, 0, (int)ms.Length); } else { // 使用 ToArray() byte[] data = ms.ToArray(); } } - .NET 4.5+ 引入了
到此這篇關(guān)于C# MemoryStream 中 ToArray 和 GetBuffer 的區(qū)別的文章就介紹到這了,更多相關(guān)C# ToArray GetBuffer內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# 利用Selenium實現(xiàn)瀏覽器自動化操作的示例代碼
這篇文章主要介紹了C# 利用Selenium實現(xiàn)瀏覽器自動化操作,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2020-09-09

