C# MemoryStream類案例詳解
MemoryStream位于System.IO命名空間,為系統(tǒng)內(nèi)存提供流式的讀寫(xiě)操作。常作為其他流數(shù)據(jù)交換時(shí)的中間對(duì)象操作。
- MemoryStream類封裝一個(gè)字節(jié)數(shù)組,在構(gòu)造實(shí)例時(shí)可以使用一個(gè)字節(jié)數(shù)組作為參數(shù),但是數(shù)組的長(zhǎng)度無(wú)法調(diào)整。使用默認(rèn)無(wú)參數(shù)構(gòu)造函數(shù)創(chuàng)建實(shí)例,可以使用Write方法寫(xiě)入,隨著字節(jié)數(shù)據(jù)的寫(xiě)入,數(shù)組的大小自動(dòng)調(diào)整。
- 在對(duì)MemoryStream類中數(shù)據(jù)流進(jìn)行讀取時(shí),可以使用seek方法定位讀取器的當(dāng)前的位置,可以通過(guò)指定長(zhǎng)度的數(shù)組一次性讀取指定長(zhǎng)度的數(shù)據(jù)。ReadByte方法每次讀取一個(gè)字節(jié),并將字節(jié)返回一個(gè)整數(shù)值。
- UnicodeEncoding類中定義了Unicode中UTF-16編碼的相關(guān)功能。通過(guò)其中的方法將字符串轉(zhuǎn)換為字節(jié),也可以將字節(jié)轉(zhuǎn)換為字符串。
MemoryStream 是一個(gè)特例,MemoryStream中沒(méi)有任何非托管資源,所以它的Dispose不調(diào)用也沒(méi)關(guān)系。托管資源.Net會(huì)自動(dòng)回收
MemoryStream繼承自Stream類。內(nèi)存流的好處是指針可以晃來(lái)晃去,也就是支CanSeek,Position,Seek()。任意讀其中一段。
在內(nèi)存流中有必要了解一下SeekOrigin枚舉
枚舉成員 | 成員值 | 描述 |
---|---|---|
Begin | 0 | 指定流的開(kāi)頭。 |
Current | 1 | 指定流內(nèi)的當(dāng)前位置。 |
End | 2 | 指定流的結(jié)尾。 |
MemoryStream提供的屬性與方法:
一、屬性
CanRead 已重寫(xiě)。獲取一個(gè)值,該值指示當(dāng)前流是否支持讀取。
CanSeek 已重寫(xiě)。獲取一個(gè)值,該值指示當(dāng)前流是否支持查找。
CanTimeout 獲取一個(gè)值,該值確定當(dāng)前流是否可以超時(shí)。(從 Stream 繼承。)
CanWrite 已重寫(xiě)。獲取一個(gè)值,該值指示當(dāng)前流是否支持寫(xiě)入。
Capacity 獲取或設(shè)置分配給該流的字節(jié)數(shù)。 這個(gè)是分配的字節(jié)數(shù)
Length 已重寫(xiě)。獲取用字節(jié)表示的流長(zhǎng)度。這個(gè)是真正占用的字節(jié)數(shù)。
Position 已重寫(xiě)。獲取或設(shè)置流中的當(dāng)前位置。
ReadTimeout 獲取或設(shè)置一個(gè)值,該值確定流在超時(shí)前嘗試讀取多長(zhǎng)時(shí)間。 (從 Stream 繼承。)
WriteTimeout 獲取或設(shè)置一個(gè)值,該值確定流在超時(shí)前嘗試寫(xiě)入多長(zhǎng)時(shí)間。 (從 Stream 繼承。)
二、方法
BeginRead 開(kāi)始異步讀操作。 (從 Stream 繼承。)
BeginWrite 開(kāi)始異步寫(xiě)操作。 (從 Stream 繼承。)
Close 關(guān)閉當(dāng)前流并釋放與之關(guān)聯(lián)的所有資源(如套接字和文件句柄)。 (從 Stream 繼承。)
CreateObjRef 創(chuàng)建一個(gè)對(duì)象,該對(duì)象包含生成用于與遠(yuǎn)程對(duì)象進(jìn)行通信的代理所需的全部相關(guān)信息。 (從 MarshalByRefObject 繼承。)
Dispose 已重載。
EndRead 等待掛起的異步讀取完成。 (從 Stream 繼承。)
EndWrite 結(jié)束異步寫(xiě)操作。 (從 Stream 繼承。)
Flush 已重寫(xiě)。 重寫(xiě) Stream.Flush 以便不執(zhí)行任何操作。
GetBuffer 返回從其創(chuàng)建此流的無(wú)符號(hào)字節(jié)數(shù)組。 是會(huì)返回所有分配的字節(jié),不管用沒(méi)用到。
GetLifetimeService 檢索控制此實(shí)例的生存期策略的當(dāng)前生存期服務(wù)對(duì)象。 (從 MarshalByRefObject 繼承。)
InitializeLifetimeService 獲取控制此實(shí)例的生存期策略的生存期服務(wù)對(duì)象。 (從 MarshalByRefObject 繼承。)
Read 已重寫(xiě)。 從當(dāng)前流中讀取字節(jié)塊并將數(shù)據(jù)寫(xiě)入 buffer 中。 搞了好久才弄明白R(shí)ead()方法的含義,第一個(gè)參數(shù),是讀取到的內(nèi)容要輸出到的字節(jié)數(shù)組,第二個(gè)參數(shù)是放在第一個(gè)參數(shù)即要輸出的數(shù)組的位置的偏移量,第三個(gè)參數(shù)是,要讀取的字符數(shù)。 用這個(gè)方法你可以任意讀取一段需要的內(nèi)存。注意,Read()方法是從當(dāng)前流的Position屬性的位置開(kāi)始讀,這就是為什么很多人測(cè)試的時(shí)候,剛剛寫(xiě)入內(nèi)存的數(shù)據(jù),Read()方法無(wú)法讀取到內(nèi)容的原因,因?yàn)閯倓倢?xiě)入內(nèi)存之后,位置恰好是在最后一位了。Read()方法當(dāng)然讀不到。此方法強(qiáng)大之處在于,你可以從一個(gè)內(nèi)存流中讀出你想要的一個(gè)片段。
ReadByte 已重寫(xiě)。 從當(dāng)前流中讀取一個(gè)字節(jié)。
Seek 已重寫(xiě)。 將當(dāng)前流中的位置設(shè)置為指定值。
SetLength 已重寫(xiě)。 將當(dāng)前流的長(zhǎng)度設(shè)為指定值。
Synchronized 在指定的 Stream 對(duì)象周圍創(chuàng)建線程安全(同步)包裝。 (從 Stream 繼承。)
ToArray 將整個(gè)流內(nèi)容寫(xiě)入字節(jié)數(shù)組,而與 Position 屬性無(wú)關(guān)。
Write 已重寫(xiě)。 使用從緩沖區(qū)讀取的數(shù)據(jù)將字節(jié)塊寫(xiě)入當(dāng)前流。 同樣注意下,第二個(gè)參數(shù)是第一個(gè)參數(shù)數(shù)組的偏移量就可以了。
WriteByte 已重寫(xiě)。 將一個(gè)字節(jié)寫(xiě)入當(dāng)前流中的當(dāng)前位置。
WriteTo 將此內(nèi)存流的整個(gè)內(nèi)容寫(xiě)入另一個(gè)流中。
以下給出使用示例代碼:
static void Main(string[] args) { //屬性測(cè)試 MemoryStream ms = new MemoryStream(); Console.WriteLine(ms.CanRead); //True 內(nèi)存流可讀 Console.WriteLine(ms.CanSeek); //True 內(nèi)存流支持查找,指針移來(lái)移去的查找 Console.WriteLine(ms.CanTimeout); //False 內(nèi)存流不支持超時(shí) Console.WriteLine(ms.CanWrite); //True 內(nèi)存流可寫(xiě) Console.WriteLine(ms.Capacity); //0 分配給該流的字節(jié)數(shù) byte[] bytes = Encoding.UTF8.GetBytes("abcdedcba"); ms.Write(bytes, 0, bytes.Length); //已將一段文本寫(xiě)入內(nèi)存 Console.WriteLine(ms.Capacity); //256 再次讀取為文本流分配的字節(jié)數(shù)已經(jīng)變成了256,看來(lái)內(nèi)存流是根據(jù)需要的多少來(lái)分配的 Console.WriteLine(ms.Length); //9 這個(gè)是流長(zhǎng)度,通常與英文的字符數(shù)一樣,真正占用的字節(jié)數(shù)。 Console.WriteLine(ms.Position); //9 流當(dāng)前的位置,該屬性可讀可設(shè)置 //Console.WriteLine(ms.ReadTimeout); 由于流不支持超時(shí),此屬性如果讀取或者設(shè)置的話會(huì)報(bào)錯(cuò) //Console.WriteLine(ms.WriteTimeout); 由于流不支持超時(shí),此屬性如果讀取或者設(shè)置的話會(huì)報(bào)錯(cuò) //方法測(cè)試 byte[] byte1 = ms.GetBuffer(); //返回?zé)o符號(hào)字節(jié)數(shù)組 差點(diǎn)被忽悠了,無(wú)符號(hào)字節(jié)數(shù)組 其實(shí)就是byte(0~255),有符號(hào)字節(jié)sbyte(-128~127) string str1 = Encoding.UTF8.GetString(byte1); Console.WriteLine(str1); //輸出 abcdedcba ms.Seek(2, SeekOrigin.Current); //設(shè)置當(dāng)前流正在讀取的位置 為開(kāi)始位置即從0開(kāi)始 //從內(nèi)存中讀取一個(gè)字節(jié) int i = ms.ReadByte(); Console.WriteLine(i); //輸出99 byte[] bytes3 = ms.ToArray(); foreach (byte b in bytes3) { Console.Write(b + "-");//用于對(duì)比 輸出 97-98-99-100-101-100-99-98-97- 可以看到 0,1,2第二位剛好是99 } MemoryStream ms2 = new MemoryStream(); byte[] bytes6 = Encoding.UTF8.GetBytes("abcde"); ms2.Write(bytes6, 0, bytes6.Length); Console.WriteLine(ms2.Position); //輸出5 寫(xiě)完之后流的位置就到了最后,因此想用read讀取必須加下面這一行代碼。 //ms2.Seek(0, SeekOrigin.Begin); //想要用Read方法讀取完整的流,必須設(shè)置當(dāng)前位置,Read是從Position的位置開(kāi)始讀。 ms2.Position = 0; //Read是從當(dāng)前位置開(kāi)始讀,這行代碼和上面一行意義一樣。 byte[] byteArray = new byte[5] { 110, 110, 110, 110, 110 }; //99是經(jīng)過(guò)YTF8解碼之后是 n ms2.Read(byteArray, 2, 1); //讀取一個(gè)字節(jié),byteArray的第一個(gè)元素中,(注意從0開(kāi)始) Console.WriteLine(Encoding.UTF8.GetString(byteArray)); //nnann //ms2.Read(byteArray, 2, 2); //Console.WriteLine(Encoding.UTF8.GetString(byteArray)); //nnabn //當(dāng)超出接收數(shù)組總長(zhǎng)度的時(shí)候,后面的元素會(huì)被移開(kāi) //設(shè)置當(dāng)前流的長(zhǎng)度 Console.WriteLine(ms.Length); //輸出9 當(dāng)前流的長(zhǎng)度是9 ms.SetLength(20); Console.WriteLine(ms.Length); //輸出20 foreach (byte b in ms.ToArray()) //將流的內(nèi)容也就是內(nèi)存中的內(nèi)容轉(zhuǎn)換字節(jié)數(shù)組 { Console.Write(b + "-"); //輸出 97-98-99-100-101-100-99-98-97-0-0-0-0-0-0-0-0-0 由于設(shè)置了長(zhǎng)度,因此空的自動(dòng)補(bǔ)0 } Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); //輸出 abcdedcba 雖然長(zhǎng)度變長(zhǎng)了,但是沒(méi)影響讀取數(shù)據(jù) MemoryStream ms1 = new MemoryStream(); byte[] bytes4 = ms1.ToArray(); Console.WriteLine("此內(nèi)存流并沒(méi)有寫(xiě)入數(shù)據(jù)(Write)" + Encoding.UTF8.GetString(bytes4));//輸出 此內(nèi)存流并沒(méi)有寫(xiě)入數(shù)據(jù)(Write) 因?yàn)閮?nèi)存為空 //下面來(lái)一個(gè)指定位置的寫(xiě)入 MemoryStream ms3 = new MemoryStream(); byte[] bytesArr = Encoding.ASCII.GetBytes("abcdefg"); ms3.Write(bytesArr, 0, bytesArr.Length); ms3.Position = 2; ms3.WriteByte(97); //97代表的是a 這段代碼的意思是,將原先第二個(gè)的c替換為a string str = Encoding.ASCII.GetString(ms3.ToArray()); Console.WriteLine(str); //輸出 abacdefg byte[] byteArr1 = Encoding.ASCII.GetBytes("kk"); ms3.Position = 4; ms3.Write(byteArr1, 0, byteArr1.Length); Console.WriteLine(Encoding.UTF8.GetString(ms3.ToArray())); //abadkkg //從第4位替換掉了兩個(gè)字節(jié)為KK Console.ReadKey(); }
接下來(lái)實(shí)現(xiàn)數(shù)據(jù)類的轉(zhuǎn)換:
using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; public class DataSwitch { /// <summary> /// 數(shù)據(jù)類對(duì)象轉(zhuǎn)成字節(jié)流 /// </summary> /// <param name="obj"></param> /// <returns></returns> /// //MemoryStream: 創(chuàng)建其支持存儲(chǔ)區(qū)為內(nèi)存的流。 //IFormatter : 提供將序列化對(duì)象格式化的功能。 public static byte[] ObjectToBytes(object obj) { using (MemoryStream ms = new MemoryStream()) { // //以二進(jìn)制格式將對(duì)象或整個(gè)連接對(duì)象圖形序列化和反序列化。 IFormatter formatter = new BinaryFormatter(); //把字符串以二進(jìn)制放進(jìn)memStream中 formatter.Serialize(ms, obj); //返回從其創(chuàng)建此流的無(wú)符號(hào)字節(jié)數(shù)組。 是會(huì)返回所有分配的字節(jié),不管用沒(méi)用到。 返回?zé)o符號(hào)字節(jié)數(shù)組 ,無(wú)符號(hào)字節(jié)數(shù)組 其實(shí)就是byte(0~255),有符號(hào)字節(jié)sbyte(-128~127) return ms.GetBuffer(); } } /// <summary> /// 字節(jié)流轉(zhuǎn)成數(shù)據(jù)類對(duì)象 /// </summary> /// <param name="bytes"></param> /// <returns></returns> public static object BytesToObject(byte[] bytes) { using (MemoryStream ms = new MemoryStream(bytes)) { // //以二進(jìn)制格式將對(duì)象或整個(gè)連接對(duì)象圖形序列化和反序列化。 IFormatter formatter = new BinaryFormatter(); //把字符串以二進(jìn)制放進(jìn)memStream中 return formatter.Deserialize(ms); } } }
到此這篇關(guān)于C# MemoryStream類案例詳解的文章就介紹到這了,更多相關(guān)C# MemoryStream類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Unity UI或3D場(chǎng)景實(shí)現(xiàn)跟隨手機(jī)陀螺儀的晃動(dòng)效果
這篇文章主要介紹了Unity UI或3D場(chǎng)景實(shí)現(xiàn)跟隨手機(jī)陀螺儀的晃動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11C# IQueryable及IEnumerable區(qū)別解析
這篇文章主要介紹了C# IQueryable及IEnumerable區(qū)別解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09使用TypeScript開(kāi)發(fā)微信小程序的方法
TypeScript是C#之父Anders Hejlsberg的又一力作,很多喜歡c#語(yǔ)法的朋友對(duì)typescript都愛(ài)不釋手,今天小編給大家介紹下TypeScript開(kāi)發(fā)微信小程序的方法,感興趣的朋友一起看看吧2016-11-11C#中JSON轉(zhuǎn)為實(shí)體類和List以及結(jié)合使用
開(kāi)發(fā)中經(jīng)常遇到將JSON字符串轉(zhuǎn)換為L(zhǎng)ist的需求,下面這篇文章主要給大家介紹了關(guān)于C#中JSON轉(zhuǎn)為實(shí)體類和List以及結(jié)合使用的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01