免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
C# 溫故而知新:Stream篇(六)

C# 溫故而知新:Stream篇(六)




C# 溫故而知新:Stream篇(


BufferedStream


目錄:



 


 


 


 


1 簡單介紹一下BufferedStream


在前幾章的講述中,我們已經(jīng)能夠掌握流的基本特性和特點,一般進行對流的處理時系統(tǒng)肩負著IO所帶來的開銷,調(diào)用十分頻繁,


這時候就應(yīng)該想個辦法去減少這種開銷,而且必須在已有Stream進行擴展,有了以上2點需求,那么我們今天的主題,


BufferedStream閃亮登場了,BufferedStream能夠?qū)崿F(xiàn)流的緩存,換句話說也就是在內(nèi)存中能夠緩存一定的數(shù)據(jù)而不是


時時給系統(tǒng)帶來負擔(dān),同時BufferedStream可以對緩存中的數(shù)據(jù)進行寫入或是讀取,所以對流的性能帶來一定的提升,


但是無法同時進行讀取或?qū)懭牍ぷ?/span>,如果不使用緩沖區(qū)也行,BufferedStream能夠保證不用緩沖區(qū)時不會降低因緩沖區(qū)帶來


的讀取或?qū)懭胄阅艿南陆?/span>


 


2 如何理解緩沖區(qū)


緩沖區(qū)是內(nèi)存中的一塊連續(xù)區(qū)域,用來緩存或臨時存儲數(shù)據(jù),也就是說流可以通過緩沖區(qū)逐步對數(shù)據(jù)進行讀取或?qū)懭氩僮鳎?/span>


BufferedStream 中的緩存區(qū)可以由用戶設(shè)定,其表現(xiàn)形式為byte數(shù)組,想象下沒有緩存區(qū)將是很可怕的,假如我們的


非固態(tài)硬盤沒有緩沖區(qū),如果我們下載速度達到驚人的10m左右,那么下載一個2G或更大的文件時,磁頭的讀寫是非常


的頻繁,直接的結(jié)果是磁頭壽命急劇減少,甚至將硬盤直接燒毀或者損壞


 


3 BufferedStream的優(yōu)勢


理解了緩沖區(qū)的重要性后,讓我們在來談下BufferedStream的優(yōu)勢,首先大家肯定覺的疑惑為什么MemoryStream 同樣


也是在內(nèi)存中對流進行操作,和BufferedStream有什么區(qū)別呢?BufferedStream并不是將所有內(nèi)容都存放到內(nèi)存中,


而MemoryStream則是BufferedStream必須跟其他流如FileStream結(jié)合使用,而MemoryStream則不用,聰明的你


肯定能夠想到,BufferedStream必然類似于一個流的包裝類,對流進行”緩存功能的擴展包裝”,所以BufferedStream的


優(yōu)勢不僅體現(xiàn)在其原有的緩存功能上,更體現(xiàn)在如何幫助原有類實現(xiàn)其功能的擴展層面上


 


4 從BufferedStream 中簡單學(xué)習(xí)下裝飾模式


如何理解裝飾模式


             我們在做項目時或者設(shè)計項目時常常會碰到這個問題 :我們該如何擴展已有的類功能或者如果擴展一系列派生類的


             功能呢,可能你立刻會想到繼承,的確不錯,但是如果你仔細看下圖并且展開一定的想象的話,你就會發(fā)現(xiàn)繼承可能


             導(dǎo)致子類的膨脹性增加,如下圖所示


           



首先還是得注意以下原則


1. 多用組合,少用繼承


利用繼承設(shè)計子類的行為,是在編譯時靜態(tài)決定的,而且所有的子類都會繼承到相同的行為。然而,如果能夠利用組合的做法擴展對象的行為,就可以在運行時動態(tài)地進行擴展。


2. 類應(yīng)設(shè)計的對擴展開放,對修改關(guān)閉。


那么我們該如何避免子類的擴張同時又實現(xiàn)Girl類原有類或派生類的新功能呢?


首先我們要達到2個目的:


1 能夠為Girl的所有派生類都實現(xiàn)新功能(不修改派生類的結(jié)構(gòu))


2 利用對象組合的方式


 


為了滿足為Girl 類所有派生類都能使用,那么我們就加上一個Girl的裝飾類GirlWrapper:



  public abstract class GirlWrapper : Girl    {        protected Girl girl;        public GirlWrapper(Girl thisGril)        {            this.girl = thisGril;        }        public override void Decrorator()        {            girl.Decrorator();        }        public override string ToString()        {            return string.Format("{0}:{1}", this.girl.GirlName, this.girl.Nation);        }    }


該類繼承了Girl類,從而保證了和其他派生類有共同的基本結(jié)構(gòu),


既然有了這個裝飾類,那我們便可以刪掉原來的Singing 接口,添加一個


SingingGirlWrapper類來實現(xiàn)對girl的包裝類,



    public class SingingGirlWrapper : GirlWrapper    {        public SingingGirlWrapper(Girl thisGril)            : base(thisGril)        {        }        public void Decorator()         {            Console.WriteLine("SingingGirlWrapper decorateor:The girl named {0} who from {1} is {2} can singing nao",                 this.GirlName, this.Nation, this.girl.GetType().Name);            base.Decrorator();        }        public override string ToString()        {            return base.ToString();        }    }


           大家不必拘泥于派生的包裝類,你完全可以建立一個新的girl包裝類來實現(xiàn)特定的功能,上述例子只是演示下派生的包裝類
          這樣的話,我們便使用了組合的方式實現(xiàn)了既保留原有的接口(或者抽象類),又動態(tài)添加了新功能


          


在使用時我們可以將派生類的對象放入裝飾類的構(gòu)造中,這樣的話,在執(zhí)行包裝類Decorator方法時,可以執(zhí)行被包裝對象的


Decorator方法和包裝類的Decorator方法從而實現(xiàn)對Girl派生類的包裝,這樣的話就能實現(xiàn)靈活的組合擴展。



static void Main(string[] args)        {            Queen queen = new Queen("Mary","Unite States");            SingingGirlWrapper sgw = new SingingGirlWrapper(queen);            sgw.Decorator();            Console.ReadLine();        }



              再次理解下裝飾模式在Stream中的作用


通過以上的例子在回到BufferStream章節(jié)中,大家肯定一眼就看出了BufferStream其實就是上述例子中的wrapper類,


而Stream 類就是其共同的父類,為了給所有的流類提供緩沖功能所以BufferedStream便誕生了,這樣的話,我們可以


不用修改其派生類結(jié)構(gòu),便能靈活組合將緩沖功能嵌入stream中



 


5 BufferedStream的構(gòu)造


BufferedStream(Stream)


其實BufferedStream的構(gòu)造主要功能還是設(shè)置緩沖區(qū)大小,如果沒有指定則默認是用4096字節(jié)的進行初始化


BufferedStream(Stream, Int32)


第二個參數(shù)是手動指定緩沖區(qū)大小


第一次使用此構(gòu)造函數(shù)初始化 BufferedStream 對象時分配共享讀/寫緩沖區(qū)。 如果所有的讀和寫都大于或等于緩沖區(qū)大小,則不使用共享緩沖區(qū)。


 


6 BufferedStream的屬性


*1 CanRead 已重寫。獲取一個值,該值指示當(dāng)前流是否支持讀取。
如果流支持讀取,則為 true;如果流已關(guān)閉或是通過只寫訪問方式打開的,則為 false。
如果從 Stream 派生的類不支持讀取,則對 StreamReader、StringReader、TextReader 的 Read、ReadByte、BeginRead、EndRead 和 Peek 方法的調(diào)用將引發(fā) NotSupportedException。
如果該流已關(guān)閉,此屬性將返回 false。


 


*2 CanSeek 已重寫。獲取一個值,該值指示當(dāng)前流是否支持查找。
如果流支持查找,則為 true;如果流已關(guān)閉或者如果流是由操作系統(tǒng)句柄(如管道或到控制臺的輸出)構(gòu)造的,則為 false。
如果從 Stream 派生的類不支持查找,則對 Length、SetLength、Position 和 Seek 的調(diào)用將引發(fā) NotSupportedException。
如果該流已關(guān)閉,此屬性將返回 false。


 


*3  CanWrite 已重寫。獲取一個值,該值指示當(dāng)前流是否支持寫入。
如果流支持寫入,則為 true;如果流已關(guān)閉或是通過只讀訪問方式打開的,則為 false。 如果從 Stream 派生的類不支持寫入,


則調(diào)用 SetLength、Write 或 WriteByte 將引發(fā) NotSupportedException。 如果該流已關(guān)閉,此屬性將返回 false。


 


*4  Length 已重寫。獲取流長度,長度以字節(jié)為單位。


 


*5  Position 已重寫。獲取當(dāng)前流內(nèi)的位置。


 get 訪問器調(diào)用 Seek 獲取基礎(chǔ)流中的當(dāng)前位置,然后根據(jù)緩沖區(qū)中的當(dāng)前位置調(diào)整此值。


 set 訪問器將以前寫入緩沖區(qū)的所有數(shù)據(jù)都復(fù)制到基礎(chǔ)流中,然后調(diào)用 Seek。


 支持搜索到超出流長度的任何位置。


 


7 BufferedStream的方法


BufferStream的方法基本上和Stream類一致,沒有其獨特的方法


關(guān)于以上方法的注意事項的大家也可參考我的第一篇


 


 簡單示例:利用socket 讀取網(wǎng)頁并保存在本地



    class Program    {        static void Main(string[] args)        {            Server server = new Server("http://www.163.com/");            server.FetchWebPageData();        }    }    public class Server    {        //端口        const int webPort = 80;        //默認接收緩存大小        byte[] receiveBufferBytes = new byte[4096];        //需要獲取網(wǎng)頁的url        private  string webPageURL;        public Server(string webPageUrl)        {            webPageURL = webPageUrl;        }       /// <summary>        ///  從該網(wǎng)頁上獲取數(shù)據(jù)       /// </summary>        public void FetchWebPageData()         {            if (!string.IsNullOrEmpty(webPageURL))            FetchWebPageData(webPageURL);            Console.ReadLine();        }        /// <summary>        /// 從該網(wǎng)頁上獲取數(shù)據(jù)        /// </summary>        /// <param name="webPageURL">網(wǎng)頁url</param>        private void FetchWebPageData(string webPageURL)         {            //通過url獲取主機信息            IPHostEntry iphe = Dns.GetHostEntry(GetHostNameBystrUrl(webPageURL));            Console.WriteLine("遠程服務(wù)器名: {0}", iphe.HostName);            //通過主機信息獲取其IP            IPAddress[] address = iphe.AddressList;            IPEndPoint ipep = new IPEndPoint(address[0], 80);            //實例化一個socket用于接收網(wǎng)頁數(shù)據(jù)            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //連接            socket.Connect(ipep);            if (socket.Connected)            {                //發(fā)送頭文件,這樣才能下載網(wǎng)頁數(shù)據(jù)                socket.Send( Encoding.ASCII.GetBytes( this.GetHeader(webPageURL)));            }            else { return; }            //接收頭一批數(shù)據(jù)            var count = socket.Receive(receiveBufferBytes);            //轉(zhuǎn)化成string             var getString = Encoding.Default.GetString(receiveBufferBytes);           //創(chuàng)建文件流            FileStream fs = new FileStream(@"d:\\Test.html", FileMode.OpenOrCreate);            //創(chuàng)建緩存流            BufferedStream bs = new BufferedStream(fs);            using (fs)            {                using (bs)                {                    byte[] finalContent = Encoding.Default.GetBytes(getString.ToCharArray());                    //將頭一批數(shù)據(jù)寫入本地硬盤                    bs.Write(finalContent, 0, finalContent.Length);                    //循環(huán)通過socket接收數(shù)據(jù)                    while (count > 0)                    {                        count = socket.Receive(receiveBufferBytes, receiveBufferBytes.Length, SocketFlags.None);                        //直接將獲取到的byte數(shù)據(jù)寫入本地硬盤                        bs.Write(receiveBufferBytes, 0, receiveBufferBytes.Length);                        Console.WriteLine(Encoding.Default.GetString(receiveBufferBytes));                    }                    bs.Flush();                    fs.Flush();                    bs.Close();                    fs.Close();                }            }        }        /// <summary>        /// 得到header        /// </summary>        /// <param name="url">網(wǎng)頁url</param>        /// <returns>header字符串</returns>        private string GetHeader(string webPageurl)         {            return "GET " + GetRelativeUrlBystrUrl(webPageurl) + " HTTP/1.1\r\nHost: "                + GetHostNameBystrUrl(webPageurl) + "\r\nConnection: Close\r\n\r\n";        }        /// <summary>        /// 得到相對路徑        /// </summary>        /// <param name="strUrl">網(wǎng)頁url</param>        /// <returns></returns>        private string GetRelativeUrlBystrUrl(string strUrl)        {            int iIndex = strUrl.IndexOf(@"//");            if (iIndex <= 0)                return "/";            string strTemp = strUrl.Substring(iIndex + 2);            iIndex = strTemp.IndexOf(@"/");            if (iIndex > 0)                return strTemp.Substring(iIndex);            else                return "/";        }        /// <summary>        /// 根據(jù)Url得到host        /// </summary>        /// <param name="strUrl">網(wǎng)頁url</param>        /// <returns></returns>        private string GetHostNameBystrUrl(string strUrl)        {            int iIndex = strUrl.IndexOf(@"//");            if (iIndex <= 0)                return "";            string strTemp = strUrl.Substring(iIndex + 2);            iIndex = strTemp.IndexOf(@"/");            if (iIndex > 0)                return strTemp.Substring(0, iIndex);            else                return strTemp;        }    }


本章總結(jié)


本章主要講述了BufferedStream的概念包括緩沖區(qū)等等,其中穿插了裝飾器模式的簡單介紹,希望大家能夠BufferedStream有更深的理解,寫文不容易,


也請大家多多關(guān)注,下一章節(jié)將介紹常用的壓縮流(非微軟類庫),謝謝大家支持!


 

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
原創(chuàng)的基于Ajax的通用(組合)查詢 - 冰戈 - 博客園
DESC加密解密
利用Java實現(xiàn)串口全雙工通訊
NIO核心概念及基本讀寫AAA
怎樣才能返回一個PChar類型從DLL函數(shù)的VB6應(yīng)用程序,而不用擔(dān)心崩潰或內(nèi)存泄漏?
Bio、Nio、Aio的用法系列之NIO客戶端(三)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服