乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      溫故而知新:Stream篇

       abin30 2019-03-19

        目錄:

      什么是Stream?

      什么是字節(jié)序列

      Stream的構(gòu)造函數(shù)

      Stream的重要屬性及方法

      Stream的示例

      Stream異步讀寫

      Stream 和其子類的類圖

      本章總結(jié)

      什么是Stream?

      MSDN 中的解釋太簡(jiǎn)潔了: 提供字節(jié)序列的一般視圖

      (我可不想這么理解,這必定讓我抓狂,我理解的流是向自然界的河流那樣清澈而又美麗,c#中的流也是一樣,許多技術(shù)或者說核心技術(shù)都需要流的幫忙)

      那什么是字節(jié)序列呢?

      其實(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)方法

      首先是構(gòu)造函數(shù)

      Stream 類有一個(gè)protected 類型的構(gòu)造函數(shù), 但是它是個(gè)抽象類,無法直接如下使用

         Stream stream = new Stream();

      所以我們自定義一個(gè)流繼承自Stream 看看哪些屬性必須重寫或自定義:

      View Code

      可以看出系統(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)使用 StreamWriterBinaryWriter 類時(shí),不要刷新 Stream 基對(duì)象。

           而應(yīng)使用該類的 FlushClose 方法,此方法確保首先將該數(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屬性在流中無法

      找到正確的位置,這點(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)前流千萬別忘記關(guān)閉!

       

      為了讓大家能夠快速理解和消化上述屬性和方法我會(huì)寫個(gè)示例并且關(guān)鍵部分會(huì)詳細(xì)說明

      復(fù)制代碼
          static void Main(string[] args)
      {
      byte[] buffer = null;

      string testString = "Stream!Hello world";
      char[] readCharArray = null;
      byte[] readBuffer = null;
      string readString = string.Empty;
      //關(guān)于MemoryStream 我會(huì)在后續(xù)章節(jié)詳細(xì)闡述
      using (MemoryStream stream = new MemoryStream())
      {
      Console.WriteLine("初始字符串為:{0}", testString);
      //如果該流可寫
      if (stream.CanWrite)
      {
      //首先我們嘗試將testString寫入流中
      //關(guān)于Encoding我會(huì)在另一篇文章中詳細(xì)說明,暫且通過它實(shí)現(xiàn)string->byte[]的轉(zhuǎn)換
      buffer = Encoding.Default.GetBytes(testString);
      //我們從該數(shù)組的第一個(gè)位置開始寫,長(zhǎng)度為3,寫完之后 stream中便有了數(shù)據(jù)
      //對(duì)于新手來說很難理解的就是數(shù)據(jù)是什么時(shí)候?qū)懭氲搅髦?,在冗長(zhǎng)的項(xiàng)目代碼面前,我碰見過很
      //多新手都會(huì)有這種經(jīng)歷,我希望能夠用如此簡(jiǎn)單的代碼讓新手或者老手們?cè)跍毓氏禄A(chǔ)
      stream.Write(buffer, 0,3);

      Console.WriteLine("現(xiàn)在Stream.Postion在第{0}位置",stream.Position+1);

      //從剛才結(jié)束的位置(當(dāng)前位置)往后移3位,到第7位
      long newPositionInStream =stream.CanSeek? stream.Seek(3, SeekOrigin.Current):0;

      Console.WriteLine("重新定位后Stream.Postion在第{0}位置", newPositionInStream+1);
      if (newPositionInStream < buffer.Length)
      {
      //將從新位置(第7位)一直寫到buffer的末尾,注意下stream已經(jīng)寫入了3個(gè)數(shù)據(jù)“Str”
      stream.Write(buffer, (int)newPositionInStream, buffer.Length - (int)newPositionInStream);
      }


      //寫完后將stream的Position屬性設(shè)置成0,開始讀流中的數(shù)據(jù)
      stream.Position = 0;

      // 設(shè)置一個(gè)空的盒子來接收流中的數(shù)據(jù),長(zhǎng)度根據(jù)stream的長(zhǎng)度來決定
      readBuffer = new byte[stream.Length];


      //設(shè)置stream總的讀取數(shù)量 ,
      //注意!這時(shí)候流已經(jīng)把數(shù)據(jù)讀到了readBuffer中
      int count = stream.CanRead?stream.Read(readBuffer, 0, readBuffer.Length):0;


      //由于剛開始時(shí)我們使用加密Encoding的方式,所以我們必須解密將readBuffer轉(zhuǎn)化成Char數(shù)組,這樣才能重新拼接成string

      //首先通過流讀出的readBuffer的數(shù)據(jù)求出從相應(yīng)Char的數(shù)量
      int charCount = Encoding.Default.GetCharCount(readBuffer, 0, count);
      //通過該Char的數(shù)量 設(shè)定一個(gè)新的readCharArray數(shù)組
      readCharArray = new char[charCount];
      //Encoding 類的強(qiáng)悍之處就是不僅包含加密的方法,甚至將解密者都能創(chuàng)建出來(GetDecoder()),
      //解密者便會(huì)將readCharArray填充(通過GetChars方法,把readBuffer 逐個(gè)轉(zhuǎn)化將byte轉(zhuǎn)化成char,并且按一致順序填充到readCharArray中)
      Encoding.Default.GetDecoder().GetChars(readBuffer, 0, count, readCharArray, 0);
      for (int i = 0; i < readCharArray.Length; i++)
      {
      readString += readCharArray[i];
      }
      Console.WriteLine("讀取的字符串為:{0}", readString);
      }

      stream.Close();
      }

      Console.ReadLine();

      }
      復(fù)制代碼


      顯示結(jié)果:

      大家需要特別注意的是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)異步的讀寫,

      復(fù)制代碼
      異步讀取
      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ù)制代碼

      大家很容易的就能發(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é)篇中

      本章總結(jié):

      本章介紹了流的基本概念和c#中關(guān)于流的基類Stream所包含的一些重要的屬性和方法,關(guān)鍵是一些方法和屬性的細(xì)節(jié)和我們操作流對(duì)象時(shí)必須注意的事項(xiàng),

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多