C#使用文件流FileStream和內(nèi)存流MemoryStream操作底層字節(jié)數(shù)組byte[]
一、Stream類概述
在.NET Framework中,文件和流是有區(qū)別的。
文件是存儲在磁盤上的數(shù)據(jù)集,它具有名稱和相應(yīng)的路徑。當(dāng)打開一個(gè)文件并對其進(jìn)行讀/寫時(shí),該文件就稱為流(stream)。
但是,流不僅僅是指打開的磁盤文件,還可以是網(wǎng)絡(luò)數(shù)據(jù)。.Net Framework允許在內(nèi)存中創(chuàng)建流。此外,在控制臺應(yīng)用程序中,鍵盤輸入和文本顯示都是流。
1. Stream類
Stream類是所有流的抽象基類。
Stream類的主要屬性有CanRead、CanWrite(是否支持讀取寫入)、CanSeek(是否支持查找)、CanTimeout(是否可以超時(shí))、Length(流的長度)、Position(獲取或設(shè)置當(dāng)前流中的位置)、ReadTimeout/WriteTimeout(獲取或設(shè)置讀、寫操作的超時(shí)時(shí)間)
Stream類的主要方法有BeginRead/EndRead(開始結(jié)束異步讀操作),BeginWrite/EndWrite(開始結(jié)束異步寫操作)、Read(讀取字節(jié)序列)、ReadByte(讀取一個(gè)字節(jié))、Seek(設(shè)置查找位置)、Write(寫入字節(jié)序列)、WriteByte(寫入一個(gè)字節(jié))、 Flush(清除流的所有緩沖區(qū)并把緩沖數(shù)據(jù)寫入基礎(chǔ)設(shè)備)、Close(關(guān)閉當(dāng)前流)。
2. FileStream、MemoryStream、BufferedStream和NetworkStream
- 文件流類FileStream:以流的形式讀、寫、打開、關(guān)閉文件。另外,它還可以用來操作諸如:管道、標(biāo)準(zhǔn)輸入/輸出等其他與文件相關(guān)的操作系統(tǒng)句柄。
- 內(nèi)存流MemoryStream類:用來在內(nèi)存中創(chuàng)建流,以暫時(shí)保持?jǐn)?shù)據(jù),因此有了它就無須在硬盤上創(chuàng)建臨時(shí)文件。它將數(shù)據(jù)封裝為無符號的字節(jié)序列,可以直接進(jìn)行讀、寫、查找操作。
- 緩沖流BufferedStream類:表示把流先添加到緩沖區(qū),再進(jìn)行數(shù)據(jù)的讀/寫操作。緩沖區(qū)是存儲區(qū)中用來緩存數(shù)據(jù)的字節(jié)塊。使用緩沖區(qū)可以減少訪問數(shù)據(jù)時(shí)對操作系統(tǒng)的調(diào)用次數(shù),增強(qiáng)系統(tǒng)的讀/寫功能。
- 網(wǎng)絡(luò)流NetworkStream類:為網(wǎng)絡(luò)訪問提供數(shù)據(jù)的基礎(chǔ)流。
注意,F(xiàn)ileStream類也有緩沖功能,在創(chuàng)建FileStream類的實(shí)例時(shí),只需要指定緩沖區(qū)的大小即可。
二、文件流類 FileStream
文件流類FileStream公開了以文件為主的Stream,既支持同步讀/寫操作,也支持異步讀/寫操作。
FileStream類的特點(diǎn)是操作字節(jié)和字節(jié)數(shù)組。這種方式不適合操作用字符數(shù)據(jù)構(gòu)成的文本文件,適合處理非文本文件。
FileStream類提供了對文件的低級而復(fù)雜的操作,因此能夠?qū)崿F(xiàn)更多高級的功能。
1、讀文件
Read,ReadByte()
//創(chuàng)建d:\file.txt的FileStream對象 FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate); byte[] bData = new byte[fstream.Length]; //設(shè)置流當(dāng)前位置為文件開始位置 fstream.Seek(0, SeekOrigin.Begin); //將文件的內(nèi)容存到字節(jié)數(shù)組中(緩存) fstream.Read(bData, 0, bData.Length); string result = Encoding.UTF8.GetString(bData); Console.WriteLine(result); if (fstream != null) { //清除此流的緩沖區(qū),使得所有緩沖的數(shù)據(jù)都寫入到文件中 fstream.Flush(); fstream.Close(); }
將字節(jié)數(shù)組轉(zhuǎn)成字符串顯示以外,字節(jié)數(shù)組還可以
//1、顯示成圖片 MemoryStream mstream = new MemoryStream(bData); Image img = Image.FromStream(mstream); //2、作為值存儲到數(shù)據(jù)庫 SqlCommand comm = new SqlCommand(); comm.Parameters.Add("images", SqlDbType.Image).Value = bData; //3、寫入文件 File.WriteAllBytes("c:\aa.txt", bData); FileStream fstream = new FileStream("c:\aa.txt"); fstream.Write(bData, 0, bData.Length);
2、分塊讀文件
int bufferSize = 5; //創(chuàng)建d:\file.txt的FileStream對象 FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read, bufferSize, false);//false表示同步讀 byte[] bData = new byte[bufferSize]; //設(shè)置流當(dāng)前位置為文件開始位置 fstream.Seek(0, SeekOrigin.Begin); int bytesRead; do { //將文件的內(nèi)容存到字節(jié)數(shù)組中(緩存) bytesRead = fstream.Read(bData, 0, bData.Length); string result = Encoding.UTF8.GetString(bData, 0, bytesRead); Console.WriteLine(result); } while (bytesRead > 0); if (fstream != null) { //清除此流的緩沖區(qū),使得所有緩沖的數(shù)據(jù)都寫入到文件中 fstream.Flush(); fstream.Close(); }
3、異步讀文件
ManualResetEvent mEvent = new ManualResetEvent(false); int bufferSize = 5; byte[] bData = new byte[bufferSize]; FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read, bufferSize, true);//false表示異步讀 AsyncCallback callback = null; callback = (IAsyncResult ar) => { int bytesRead = fstream.EndRead(ar); Console.WriteLine(Encoding.UTF8.GetString(bData, 0, bytesRead)); if (bytesRead > 0) { fstream.BeginRead(bData, 0, bufferSize, callback, null);//繼續(xù)讀 } else { fstream.Close(); mEvent.Set();//讀取完畢,發(fā)送信號 } }; IAsyncResult async = fstream.BeginRead(bData, 0, bufferSize, callback, null); mEvent.WaitOne(5000, false); Console.WriteLine("讀取完成");
備注:IAsyncResult 接口的成員
AsyncState 獲取一個(gè)用戶定義的對象,該對象限定或包含有關(guān)異步操作的信息。
AsyncWaitHandle 獲取用于等待異步操作完成的 WaitHandle。
CompletedSynchronously 獲取一個(gè)值,該值指示異步操作是否同步完成。
IsCompleted 獲取一個(gè)值,該值指示異步操作是否已完成。
4、寫文件
Write,WriteByte(Byte)
//創(chuàng)建d:\file.txt的FileStream對象 FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate); byte[] bData = Encoding.UTF8.GetBytes("test filestream"); //設(shè)置流當(dāng)前位置為文件開始位置 fstream.Seek(0, SeekOrigin.Begin); //將字節(jié)數(shù)組中的內(nèi)容寫入文件 fstream.Write(bData, 0, bData.Length); if (fstream != null) { //清除此流的緩沖區(qū),使得所有緩沖的數(shù)據(jù)都寫入到文件中 fstream.Flush(); fstream.Close(); }
三、內(nèi)存流MemoryStream類
內(nèi)存流相對字節(jié)數(shù)組而言,具有流特有的特性,并且容量可自動(dòng)增長。
在數(shù)據(jù)加密以及對長度不定的數(shù)據(jù)進(jìn)行緩存等場合,使用內(nèi)存流比較方便。
下面的代碼示例演示如何讀取和寫入將內(nèi)存用作后備存儲的數(shù)據(jù)。
int count; UnicodeEncoding uniEncoding = new UnicodeEncoding(); //創(chuàng)建要寫入流的數(shù)據(jù) byte[] firstString = uniEncoding.GetBytes("Invalid file path characters are: "); byte[] secondString = uniEncoding.GetBytes(Path.GetInvalidPathChars()); using (MemoryStream memStream = new MemoryStream(100)) { // 將第一個(gè)字符串寫入流. memStream.Write(firstString, 0, firstString.Length); // 將第二個(gè)字符串按字節(jié)寫入流. count = 0; while (count < secondString.Length) { memStream.WriteByte(secondString[count++]); } // 將流屬性寫入控制臺. Console.WriteLine("Capacity = {0}, Length = {1}, Position = {2}\n", memStream.Capacity.ToString(), memStream.Length.ToString(), memStream.Position.ToString()); // 將位置設(shè)置為流的開始. memStream.Seek(0, SeekOrigin.Begin); // 從流中讀取前20個(gè)字節(jié). byte[] byteArray = new byte[memStream.Length]; count = memStream.Read(byteArray, 0, 20); // 一個(gè)字節(jié)一個(gè)字節(jié)地讀取剩下的字節(jié). while (count < memStream.Length) { byteArray[count++] = Convert.ToByte(memStream.ReadByte()); } // 將字節(jié)數(shù)組解碼為char數(shù)組并將其寫入控制臺. char[] charArray = new char[uniEncoding.GetCharCount(byteArray, 0, count)]; uniEncoding.GetDecoder().GetChars(byteArray, 0, count, charArray, 0); Console.WriteLine(charArray); }
ToArray()與GetBuffer()的區(qū)別:
//將流中的數(shù)據(jù)復(fù)制到一個(gè)byte[]中,速度比GetBuffer()稍慢,但不會將無用的空數(shù)據(jù)放入buffer中。 byte[] byteArray = memStream.ToArray(); //把流中的Buffer的引用傳遞出來,速度較快,Buffer的大小有流的Capacity決定的,但會傳無用的空數(shù)據(jù)。 byte[] byteArray = memStream.GetBuffer();
到此這篇關(guān)于C#使用文件流FileStream和內(nèi)存流MemoryStream操作底層字節(jié)數(shù)組byte[]的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#結(jié)合JavaScript實(shí)現(xiàn)秒殺倒計(jì)時(shí)的方法
這篇文章主要介紹了C#結(jié)合JavaScript實(shí)現(xiàn)秒殺倒計(jì)時(shí)的方法,涉及C#結(jié)合javascript操作時(shí)間的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04使用C#發(fā)送Http請求實(shí)現(xiàn)模擬登陸實(shí)例
本文主要介紹了使用C#發(fā)送Http請求實(shí)現(xiàn)模擬登陸實(shí)例,模擬登陸的原理簡單,想要了解的朋友可以了解一下。2016-10-10C#如何將查詢到的數(shù)據(jù)庫里面的數(shù)據(jù)輸出到textbox控件
這篇文章主要介紹了C#如何將查詢到的數(shù)據(jù)庫里面的數(shù)據(jù)輸出到textbox控件問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07提高C# StringBuilder操作性能優(yōu)化的方法
本篇文章主要介紹使用C# StringBuilder 的項(xiàng)目實(shí)踐,用于減少內(nèi)存分配,提高字符串操作的性能。對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-11-11C# WinForm實(shí)現(xiàn)窗體上控件自由拖動(dòng)功能示例
這篇文章主要介紹了C# WinForm實(shí)現(xiàn)窗體上控件自由拖動(dòng)功能,涉及WinForm控件屬性及事件響應(yīng)相關(guān)操作技巧,需要的朋友可以參考下2017-07-07C#通過cmd調(diào)用7z軟件實(shí)現(xiàn)壓縮和解壓文件
這篇文章介紹了C#通過cmd調(diào)用7z軟件實(shí)現(xiàn)壓縮和解壓文件的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04利用C#版OpenCV實(shí)現(xiàn)圓心求取實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于如何利用C#版OpenCV實(shí)現(xiàn)圓心求取的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05