目錄: Stream 和其子類的類圖 MSDN 中的解釋太簡(jiǎn)潔了: 提供字節(jié)序列的一般視圖 (我可不想這么理解,這必定讓我抓狂,我理解的流是向自然界的河流那樣清澈而又美麗,c#中的流也是一樣,許多技術(shù)或者說核心技術(shù)都需要流的幫忙) 其實(shí)簡(jiǎn)單的來理解的話字節(jié)序列指的是: 字節(jié)對(duì)象都被存儲(chǔ)為連續(xù)的字節(jié)序列,字節(jié)按照一定的順序進(jìn)行排序組成了字節(jié)序列 那什么關(guān)于流的解釋可以抽象為下列情況: 打個(gè)比方:一條河中有一條魚游過,這個(gè)魚就是一個(gè)字節(jié),這個(gè)字節(jié)包括魚的眼睛,嘴巴,等組成8個(gè)二進(jìn)制,顯然這條河就是我們的核心對(duì)象:流 馬上進(jìn)入正題,讓我們來解釋下c#的 Stream 是如何使用的 讓我們直接溫故或?qū)W習(xí)下Stream類的結(jié)構(gòu),屬性和相關(guān)方法 Stream 類有一個(gè)protected 類型的構(gòu)造函數(shù), 但是它是個(gè)抽象類,無(wú)法直接如下使用 Stream stream = new Stream(); 所以我們自定義一個(gè)流繼承自Stream 看看哪些屬性必須重寫或自定義: ![]() 可以看出系統(tǒng)自動(dòng)幫我們實(shí)現(xiàn)了Stream 的抽象屬性和屬性方法 1: CanRead: 只讀屬性,判斷該流是否能夠讀?。?/p> 2: CanSeek: 只讀屬性,判斷該流是否支持跟蹤查找 3: CanWrite: 只讀屬性,判斷當(dāng)前流是否可寫 *4: void Flush():這點(diǎn)必須說得仔細(xì)些: 當(dāng)我們使用流寫文件時(shí),數(shù)據(jù)流會(huì)先進(jìn)入到緩沖區(qū)中,而不會(huì)立刻寫入文件,當(dāng)執(zhí)行這個(gè)方法后,緩沖區(qū)的數(shù)據(jù)流會(huì)立即注入基礎(chǔ)流 MSDN中的描述:使用此方法將所有信息從基礎(chǔ)緩沖區(qū)移動(dòng)到其目標(biāo)或清除緩沖區(qū),或者同時(shí)執(zhí)行這兩種操作。根據(jù)對(duì)象的狀態(tài),可能需要修 改流內(nèi)的當(dāng)前位置(例如,在基礎(chǔ)流支持查找的情況下即如此)當(dāng)使用 StreamWriter 或 BinaryWriter 類時(shí),不要刷新 Stream 基對(duì)象。 而應(yīng)使用該類的 Flush 或 Close 方法,此方法確保首先將該數(shù)據(jù)刷新至基礎(chǔ)流,然后再將其寫入文件。 (紅色部分為關(guān)鍵請(qǐng)大家務(wù)必能夠理解,今后會(huì)在相應(yīng)的章節(jié)中介紹) 5: Length:表示流的長(zhǎng)度 *6: Position屬性:(非常重要) 雖然從字面中可以看出這個(gè)Position屬性只是標(biāo)示了流中的一個(gè)位置而已,可是我們?cè)趯?shí)際開發(fā)中會(huì)發(fā)現(xiàn)這個(gè)想法會(huì)非常的幼稚, 很多asp.net項(xiàng)目中文件或圖片上傳中很多朋友會(huì)經(jīng)歷過這樣一個(gè)痛苦:Stream對(duì)象被緩存了,導(dǎo)致了Position屬性在流中無(wú)法 找到正確的位置,這點(diǎn)會(huì)讓人抓狂,其實(shí)解決這個(gè)問題很簡(jiǎn)單,聰明的你肯定想到了,其實(shí)我們每次使用流前必須將Stream.Position 設(shè)置成0就行了,但是這還不能根本上解決問題,最好的方法就是用Using語(yǔ)句將流對(duì)象包裹起來,用完后關(guān)閉回收即可。 *7: abstract int Read(byte[] buffer, int offset, int count) 這個(gè)方法包含了3個(gè)關(guān)鍵的參數(shù):緩沖字節(jié)數(shù)組,位移偏量和讀取字節(jié)個(gè)數(shù),每次讀取一個(gè)字節(jié)后會(huì)返回一個(gè)緩沖區(qū)中的總字節(jié)數(shù) 第一個(gè)參數(shù):這個(gè)數(shù)組相當(dāng)于一個(gè)空盒子,Read()方法每次讀取流中的一個(gè)字節(jié)將其放進(jìn)這個(gè)空盒子中。(全部讀完后便可使用buffer字節(jié)數(shù)組了) 第二個(gè)參數(shù):表示位移偏量,告訴我們從流中哪個(gè)位置(偏移量)開始讀取。 最后一個(gè)參數(shù):就是讀取多少字節(jié)數(shù)。 返回值便是總共讀取了多少字節(jié)數(shù). *8: abstract long Seek(long offset, SeekOrigin origin) 大家還記得Position屬性么?其實(shí)Seek方法就是重新設(shè)定流中的一個(gè)位置,在說明offset參數(shù)作用之前大家先來了解下SeekOrigin這個(gè)枚舉: 如果 offset 為負(fù),則要求新位置位于 origin 指定的位置之前,其間隔相差 offset 指定的字節(jié)數(shù)。如果 offset 為零 (0),則要求新位置位于由 origin 指定的位置處。 如果 offset 為正,則要求新位置位于 origin 指定的位置之后,其間隔相差 offset 指定的字節(jié)數(shù). Stream. Seek(-3,Origin.End); 表示在流末端往前數(shù)第3個(gè)位置 Stream. Seek(0,Origin.Begin); 表示在流的開頭位置 Stream. Seek(3,Orig`in.Current); 表示在流的當(dāng)前位置往后數(shù)第三個(gè)位置 查找之后會(huì)返回一個(gè)流中的一個(gè)新位置。其實(shí)說道這大家就能理解Seek方法的精妙之處了吧 *9: abstract void Write(byte[] buffer,int offset,int count) 這個(gè)方法包含了3個(gè)關(guān)鍵的參數(shù):緩沖字節(jié)數(shù)組,位移偏量和讀取字節(jié)個(gè)數(shù) 和read方法不同的是 write方法中的第一個(gè)參數(shù)buffer已經(jīng)有了許多byte類型 的數(shù)據(jù),我們只需通過設(shè)置 offset和count來將buffer中的數(shù)據(jù)寫入流中 *10: virtual void Close() 關(guān)閉流并釋放資源,在實(shí)際操作中,如果不用using的話,別忘了使用完流之后將其關(guān)閉 這個(gè)方法特別重要,使用完當(dāng)前流千萬(wàn)別忘記關(guān)閉! 為了讓大家能夠快速理解和消化上述屬性和方法我會(huì)寫個(gè)示例并且關(guān)鍵部分會(huì)詳細(xì)說明 static void Main(string[] args)
大家需要特別注意的是stream.Positon這個(gè)很神奇的屬性,在復(fù)雜的程序中,往往流對(duì)象操作也會(huì)很復(fù)雜, 一定要切記將stream.Positon設(shè)置在你所需要的正確位置,還有就是 using語(yǔ)句的使用,它會(huì)自動(dòng)銷毀stream對(duì)象, 當(dāng)然Stream.Close()大家都懂的 接著讓我們來說下關(guān)于流中怎么實(shí)現(xiàn)異步操作 在Stream基類中還有幾個(gè)關(guān)鍵方法,它們能夠很好實(shí)現(xiàn)異步的讀寫, 異步讀取 public virtual IAsyncResult BeginRead(byte[] buffer,int offset,int count,AsyncCallback callback,Object state) 異步寫 public virtual IAsyncResult BeginWrite( byte[] buffer, int offset, int count, AsyncCallback callback, Object state ) 結(jié)束異步讀取 public virtual int EndRead( IAsyncResult asyncResult ) 結(jié)束異步寫 public virtual void EndWrite( IAsyncResult asyncResult ) 大家很容易的就能發(fā)現(xiàn)前兩個(gè)方法實(shí)現(xiàn)了IAsyncResult接口,后2個(gè)end方法也順應(yīng)帶上了一個(gè)IAsyncResult參數(shù), 其實(shí)并不復(fù)雜,(必須說明下 每次調(diào)用 Begin方法時(shí)都必須調(diào)用一次 相對(duì)應(yīng)的end方法) 和一般同步read或write方法一致的是,他們可以當(dāng)做同步方法使用,但是在復(fù)雜的情況下可能也難逃阻塞崩潰等等,但是一旦啟用了 異步之后,這些類似于阻塞問題會(huì)不復(fù)存在,可見微軟對(duì)于異步的支持正在加大。 最后是有關(guān)c#中Stream類和其子類的類圖 類圖呢?大家肯定會(huì)這么想把 ^^ 為什么這個(gè)在目錄中是灰色的?其實(shí)我個(gè)人覺得這個(gè)類圖不應(yīng)該放在這篇博文中,原因是我們真正理解并熟練操作了Stream的所有子類?(大牛除外) (這也是我寫后續(xù)文章的動(dòng)力之一,寫博能很好的提升知識(shí)點(diǎn)的吸收,不僅能幫助別人,也能提高自己的對(duì)于知識(shí)點(diǎn)的理解),所以我想把類圖放在這 個(gè)系類的總結(jié)篇中 本章介紹了流的基本概念和c#中關(guān)于流的基類Stream所包含的一些重要的屬性和方法,關(guān)鍵是一些方法和屬性的細(xì)節(jié)和我們操作流對(duì)象時(shí)必須注意的事項(xiàng), |
|