C#?MemoryStream中ToArray和GetBuffer的區(qū)別小小結(jié)
前言
MemoryStream 中的 GetBuffer() 和 ToArray() 是兩個(gè)用于獲取流數(shù)據(jù)的方法,但它們的核心區(qū)別在于 數(shù)據(jù)范圍、內(nèi)存占用和安全性。
一、核心區(qū)別
| 特性 | GetBuffer() | ToArray() |
|---|---|---|
| 返回內(nèi)容 | 返回 底層緩沖區(qū)的完整數(shù)組 (包含未使用的空間)。 | 返回 僅包含有效數(shù)據(jù)的數(shù)組 (排除未使用的空間)。 |
| 內(nèi)存占用 | 可能包含大量未使用的空字節(jié)(0 填充), 占用更多內(nèi)存。 | 僅包含實(shí)際寫入的數(shù)據(jù), 內(nèi)存更高效。 |
| 性能 | 速度快(直接返回引用,無需復(fù)制)。 | 速度較慢(需復(fù)制數(shù)據(jù)到新數(shù)組)。 |
| 安全性 | 可能暴露未初始化的字節(jié)(0 填充), 可能導(dǎo)致數(shù)據(jù)污染或解析錯(cuò)誤。 | 僅返回有效數(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í)際數(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個(gè)0)。 - 如果直接使用
buffer,可能導(dǎo)致數(shù)據(jù)解析錯(cuò)誤(例如,將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í)際數(shù)據(jù)長度)
Console.WriteLine(BitConverter.ToString(bytes));//輸出:74-65-73-74
}
}
}
- 優(yōu)勢(shì):
- 僅返回實(shí)際寫入的數(shù)據(jù)(
Length指定的范圍),無多余0填充。 - 更適合需要精確數(shù)據(jù)的場(chǎng)景(如序列化、加密、文件傳輸)。
- 僅返回實(shí)際寫入的數(shù)據(jù)(
三、關(guān)鍵場(chǎng)景對(duì)比
| 場(chǎng)景 | 推薦方法 | 原因 |
|---|---|---|
| 需要高效訪問底層緩沖區(qū)(如直接操作內(nèi)存) | GetBuffer() | 避免復(fù)制開銷,但需確保僅使用有效數(shù)據(jù)范圍。 |
| 需要精確數(shù)據(jù)(如網(wǎng)絡(luò)傳輸、文件保存) | ToArray() | 確保數(shù)據(jù)不含未使用的 0,避免解析錯(cuò)誤(如 Excel 文件損壞問題)。 |
| 流的容量遠(yuǎn)大于實(shí)際數(shù)據(jù) | ToArray() | 避免浪費(fèi)內(nèi)存(如示例中 256 字節(jié) vs 4 字節(jié))。 |
| 需要避免未初始化字節(jié)的干擾 | ToArray() | 僅返回有效數(shù)據(jù),安全性更高。 |
四、注意事項(xiàng)
1. 異常情況
GetBuffer()的限制:- 如果
MemoryStream是通過MemoryStream(byte[] buffer, bool writable)構(gòu)造函數(shù)創(chuàng)建,并且publiclyVisible參數(shù)未設(shè)置為true,則調(diào)用GetBuffer()會(huì)拋出UnauthorizedAccessException。 - 解決方案:改用
ToArray()或確保構(gòu)造時(shí)允許公開訪問緩沖區(qū)。
- 如果
2. 容量與長度
CapacityvsLength:Capacity是底層緩沖區(qū)的總大小(如默認(rèn)256)。Length是實(shí)際寫入數(shù)據(jù)的大小(如4)。GetBuffer()返回的數(shù)組長度等于Capacity,而ToArray()返回的數(shù)組長度等于Length。
3. 性能權(quán)衡
- 大數(shù)據(jù)場(chǎng)景:
- 如果需要頻繁操作大容量數(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ò)傳輸或第三方庫解析時(shí),
ToArray()更可靠(如解決 Excel 文件損壞問題)。 - 通過
TryGetBuffer()替代GetBuffer(),避免異常風(fēng)險(xiǎn)。- .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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#使用AutoResetEvent實(shí)現(xiàn)同步
這篇文章主要為大家詳細(xì)介紹了C#使用AutoResetEvent實(shí)現(xiàn)同步的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
c#實(shí)現(xiàn)最簡(jiǎn)潔的快速排序(你絕對(duì)可以看懂)
這篇文章主要給大家介紹了關(guān)于利用c#實(shí)現(xiàn)如何最簡(jiǎn)潔的快速排序,實(shí)現(xiàn)的方法你絕對(duì)可以看懂,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用c#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
C#在PDF中繪制不同風(fēng)格類型的文本方法實(shí)例
這篇文章主要給大家介紹了關(guān)于C#在PDF中繪制不同風(fēng)格類型的文本的相關(guān)資料,文中通過圖文以及示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
C# 利用Selenium實(shí)現(xiàn)瀏覽器自動(dòng)化操作的示例代碼
這篇文章主要介紹了C# 利用Selenium實(shí)現(xiàn)瀏覽器自動(dòng)化操作,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2020-09-09

