日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

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

發(fā)布時(shí)間:2023/12/10 C# 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C# 温故而知新:Stream篇(六) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

C# 溫故而知新:Stream篇(

BufferedStream

目錄:

  • 簡(jiǎn)單介紹一下BufferedStream
  • 如何理解緩沖區(qū)?
  • BufferedStream的優(yōu)勢(shì)
  • 從BufferedStream 中學(xué)習(xí)裝飾模式
  •     如何理解裝飾模式
  •     再次理解下裝飾模式在Stream中的作用
  • ?BufferedStream的構(gòu)造
  • ?BufferedStream的屬性
  • ?BufferedStream的方法
  • ?簡(jiǎn)單示例:利用socket 讀取網(wǎng)頁(yè)并保存在本地
  • ?本章總結(jié)

?

?

?

?

1 簡(jiǎn)單介紹一下BufferedStream

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

這時(shí)候就應(yīng)該想個(gè)辦法去減少這種開(kāi)銷(xiāo),而且必須在已有Stream進(jìn)行擴(kuò)展,有了以上2點(diǎn)需求,那么我們今天的主題,

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

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

但是無(wú)法同時(shí)進(jìn)行讀取或?qū)懭牍ぷ?/span>,如果不使用緩沖區(qū)也行,BufferedStream能夠保證不用緩沖區(qū)時(shí)不會(huì)降低因緩沖區(qū)帶來(lái)

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

?

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

緩沖區(qū)是內(nèi)存中的一塊連續(xù)區(qū)域,用來(lái)緩存或臨時(shí)存儲(chǔ)數(shù)據(jù),也就是說(shuō)流可以通過(guò)緩沖區(qū)逐步對(duì)數(shù)據(jù)進(jìn)行讀取或?qū)懭氩僮?#xff0c;

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

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

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

?

3 BufferedStream的優(yōu)勢(shì)

理解了緩沖區(qū)的重要性后,讓我們?cè)趤?lái)談下BufferedStream的優(yōu)勢(shì),首先大家肯定覺(jué)的疑惑為什么MemoryStream 同樣

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

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

肯定能夠想到,BufferedStream必然類(lèi)似于一個(gè)流的包裝類(lèi),對(duì)流進(jìn)行”緩存功能的擴(kuò)展包裝”,所以BufferedStream的

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

?

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

如何理解裝飾模式

???????????? 我們?cè)谧鲰?xiàng)目時(shí)或者設(shè)計(jì)項(xiàng)目時(shí)常常會(huì)碰到這個(gè)問(wèn)題 :我們?cè)撊绾螖U(kuò)展已有的類(lèi)功能或者如果擴(kuò)展一系列派生類(lèi)的

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

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

???????????

首先還是得注意以下原則

1. 多用組合,少用繼承

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

2. 類(lèi)應(yīng)設(shè)計(jì)的對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。

那么我們?cè)撊绾伪苊庾宇?lèi)的擴(kuò)張同時(shí)又實(shí)現(xiàn)Girl類(lèi)原有類(lèi)或派生類(lèi)的新功能呢?

首先我們要達(dá)到2個(gè)目的:

1 能夠?yàn)镚irl的所有派生類(lèi)都實(shí)現(xiàn)新功能(不修改派生類(lèi)的結(jié)構(gòu))

2 利用對(duì)象組合的方式

?

為了滿(mǎn)足為Girl 類(lèi)所有派生類(lèi)都能使用,那么我們就加上一個(gè)Girl的裝飾類(lèi)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);}}

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

既然有了這個(gè)裝飾類(lèi),那我們便可以刪掉原來(lái)的Singing 接口,添加一個(gè)

SingingGirlWrapper類(lèi)來(lái)實(shí)現(xiàn)對(duì)girl的包裝類(lèi),

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();}}

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

??????????

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

Decorator方法和包裝類(lèi)的Decorator方法從而實(shí)現(xiàn)對(duì)Girl派生類(lèi)的包裝,這樣的話就能實(shí)現(xiàn)靈活的組合擴(kuò)展。

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


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

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

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

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

?

5 BufferedStream的構(gòu)造

BufferedStream(Stream)

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

BufferedStream(Stream, Int32)

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

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

?

6 BufferedStream的屬性

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

?

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

?

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

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

?

*4 ?Length 已重寫(xiě)。獲取流長(zhǎng)度,長(zhǎng)度以字節(jié)為單位。

?

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

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

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

?支持搜索到超出流長(zhǎng)度的任何位置。

?

7 BufferedStream的方法

BufferStream的方法基本上和Stream類(lèi)一致,沒(méi)有其獨(dú)特的方法

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

?

8??簡(jiǎn)單示例:利用socket 讀取網(wǎng)頁(yè)并保存在本地

class Program{static void Main(string[] args){Server server = new Server("http://www.163.com/");server.FetchWebPageData();}}public class Server{//端口const int webPort = 80;//默認(rèn)接收緩存大小byte[] receiveBufferBytes = new byte[4096];//需要獲取網(wǎng)頁(yè)的urlprivate string webPageURL;public Server(string webPageUrl){webPageURL = webPageUrl;}/// <summary>/// 從該網(wǎng)頁(yè)上獲取數(shù)據(jù)/// </summary>public void FetchWebPageData() {if (!string.IsNullOrEmpty(webPageURL))FetchWebPageData(webPageURL);Console.ReadLine();}/// <summary>/// 從該網(wǎng)頁(yè)上獲取數(shù)據(jù)/// </summary>/// <param name="webPageURL">網(wǎng)頁(yè)url</param>private void FetchWebPageData(string webPageURL) {//通過(guò)url獲取主機(jī)信息IPHostEntry iphe = Dns.GetHostEntry(GetHostNameBystrUrl(webPageURL));Console.WriteLine("遠(yuǎn)程服務(wù)器名: {0}", iphe.HostName);//通過(guò)主機(jī)信息獲取其IPIPAddress[] address = iphe.AddressList;IPEndPoint ipep = new IPEndPoint(address[0], 80);//實(shí)例化一個(gè)socket用于接收網(wǎng)頁(yè)數(shù)據(jù)Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//連接 socket.Connect(ipep);if (socket.Connected){//發(fā)送頭文件,這樣才能下載網(wǎng)頁(yè)數(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ù)寫(xiě)入本地硬盤(pán)bs.Write(finalContent, 0, finalContent.Length);//循環(huán)通過(guò)socket接收數(shù)據(jù)while (count > 0){count = socket.Receive(receiveBufferBytes, receiveBufferBytes.Length, SocketFlags.None);//直接將獲取到的byte數(shù)據(jù)寫(xiě)入本地硬盤(pán)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)頁(yè)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>/// 得到相對(duì)路徑/// </summary>/// <param name="strUrl">網(wǎng)頁(yè)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);elsereturn "/";}/// <summary>/// 根據(jù)Url得到host/// </summary>/// <param name="strUrl">網(wǎng)頁(yè)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);elsereturn strTemp;}}

本章總結(jié)

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

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

?

轉(zhuǎn)載于:https://www.cnblogs.com/JimmyZheng/archive/2012/04/25/2470277.html

總結(jié)

以上是生活随笔為你收集整理的C# 温故而知新:Stream篇(六)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。