u<b>本節學習目标:</b>
n了解讀寫記憶體流MemoryStream的特點
n學習如何建立記憶體流MemoryStream
n了解讀寫緩存流BufferedStream
n學習如何建立緩存流BufferedStream
前面第二節,介紹了檔案流類FileStream,本節要繼續介紹其他流。那麼什麼是流?在.net程式中,涉及的輸入和輸出都是通過流來實作的。流是串行化裝置的抽象表示,流以讀/寫位元組的方式從存儲器讀/寫資料。存儲器是存儲媒介,磁盤或記憶體都是存儲器。正如除磁盤外還存在着多種存儲器,除檔案流之外也存在多種流,例如:網絡流、記憶體流、緩存流等。類Stream及其派生類組成流的家族。如圖3-12所示:
圖3-12 流家族類關系圖
所有流的類都是從類Stream派生出來的。類Stream是所有流的抽象基類,是以它不能被執行個體化為對象,隻能通過變量引用派生類的對象。Stream變量所引用對象具有一下一種或多種功能:
n讀:通過Read()或ReadByte()方法實作讀資料;
n寫:通過Write()或WriteByte()方法實作寫資料;
n定位:通過Position屬性和Seek()方法實作定位。
<b></b><b></b>
<b>注意:</b>
派生的流對象隻能支援這些功能中的一部分。例如:NetworkStream不支援定位。可以利用從Stream派生出來的對象的CanRead、CanWrite和CanSeek屬性判斷流對象支援哪些操作。
另外,對于類MemoryStream,有兩點需要說明:
n對記憶體而不是對磁盤進行資料讀寫;
n減少了對臨時緩沖區和檔案的需要。
而對于類BufferedStream,有四點需要說明:
n對緩沖區進行資料讀寫;
n允許作業系統建立自己的緩沖區;
n輸入/輸出效率高且速度更快;
n在網絡通訊的時候經常會使用到。
類MemoryStream建立這樣的流,該流以記憶體而不是磁盤或網絡連接配接作為支援存儲區。類MemoryStream封裝以無符号位元組數組形式存儲的資料,該數組在建立MemoryStream對象時被初始化,或者該數組可建立為空數組。可在記憶體中直接通路這些封裝的資料。記憶體流可降低應用程式中對臨時緩沖區和臨時檔案的需要。
FileStream對象與MemoryStream對象有很大差別,主要展現在以下方面:
nFileStream對象的資料來自檔案,而MemoryStream對象的資料來自記憶體緩沖區。這兩個類都繼承自Stream類。
nMemoryStream的資料來自記憶體中的一塊連續區域,這塊區域稱為“緩沖區(Buffer)”。可以把緩沖區看成一個數組,每個數組元素可以存放一個位元組的資料。
n在建立MemoryStream對象時,可以指定緩沖區的大小,并且可以在需要的時候更改。
類MemoryStream的構造函數有7種重載,我們這裡重點介紹三種,如表3-16所示:
表3-16 類MemoryStream的常用構造函數
<b>名稱</b>
<b>說明</b>
MemoryStream ()
使用初始化為零的可擴充容量初始化 MemoryStream 類的新執行個體。
MemoryStream (byte[])
基于指定的位元組數組初始化 MemoryStream 類的無法調整大小的新執行個體。
MemoryStream (byte[], Boolean)
使用按指定要求設定的 CanWrite 屬性基于指定的位元組數組初始化 MemoryStream 類的無法調整大小的新執行個體。
記憶體流對象還有一些重要的屬性。其中Length屬性代表了記憶體流對象存放的資料的真實長度,而Capacity屬性則代表了配置設定給記憶體流的記憶體空間大小。可以使用位元組數組建立一個固定大小的MemoryStream。
n<b>小實驗1:</b>
<b></b>
MemoryStream mem = new MemoryStream(buffer);
//這時,無法再設定Capacity屬性的大小。
n<b>小實驗2:</b>
MemoryStream mem = new MemoryStream(buffer, false);
//這時,CanWrite屬性就被設定為false 。
這樣在記憶體流對象被執行個體化時,一些屬性就被影響了。
本案例您将學習到:如何通過使用記憶體流的屬性、方法來擷取記憶體流的占用空間資訊及改變記憶體流空間大小。
u實驗步驟(1):
由圖3-13所示,從工具箱之中拖拽五個Label控件到Form窗體上,拖拽一個Button控件。
圖3-13 MemoryStream類案例界面圖
u實驗步驟(2):
用滑鼠輕按兩下所有Button控件,進入.cs檔案編輯狀态準備進行開發。代碼加下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace FileOptionApplication
{
public partial class Form14 : Form
{
public Form14()
{
InitializeComponent();
}
//建立位元組數組
byte[] buffer = new byte[600];
/// <summary>
/// 擷取測試性資料
/// </summary>
private void GetTestData()
for (int i = 0; i < 600; i++)
{
buffer[i] = (byte)(i % 256);
//byte類型的數最大不能超過255,用256取模實作
}
/// button1按鈕的滑鼠單擊Click事件
private void button1_Click(object sender, EventArgs e)
//建立測試資料
GetTestData();
//建立記憶體流對象,初始配置設定50位元組的緩沖區
MemoryStream mem = new MemoryStream(50);
//向記憶體流中寫入位元組數組的所有資料
mem.Write(buffer,0,buffer.GetLength(0));
//使用從緩沖區讀取的資料将位元組塊寫入目前流。
//參數:
//1、buffer從中寫入資料的緩沖區。
//2、offset buffer中的位元組偏移量,從此處開始寫入。
//3、count最多寫入的位元組數。
//GetLength(0) 為 GetLength 的一個示例,它傳回 Array 的第一維中的元素個數。
label1.Text = "寫入資料後的記憶體流長度是:"+mem.Length.ToString();
label2.Text = "配置設定給記憶體流的緩沖區大小:"+mem.Capacity.ToString();
mem.SetLength(500);
label3.Text = "調用SetLength方法後的記憶體流長度:" + mem.Length.ToString();
mem.Capacity = 620;//注意:此值不能小于Length屬性
label4.Text = "調用Capacity方法後緩沖區大小:" + mem.Capacity.ToString();
//将讀寫指針移到距流開頭10個位元組的位置
mem.Seek(45, SeekOrigin.Begin);
label5.Text = "記憶體中的資訊是:"+mem.ReadByte().ToString();
}
}
u實驗步驟(3):
調試、運作程式,得到效果如圖3-14所示:
圖3-14 MemoryStream類案例運作效果圖
BufferedStream也在共享緩沖區中緩沖讀取和寫入。假設您幾乎始終執行一系列讀取或寫入操作,而很少在讀取和寫入之間切換。類BufferedStream的構造函數有2種重載,如表3-17所示:
表3-17 類BufferedStream的常用構造函數
<a>BufferedStream (Stream)</a>
使用預設的緩沖區大小 4096 位元組初始化 BufferedStream 類的新執行個體。
<a>BufferedStream (Stream, Int32)</a>
使用指定的緩沖區大小初始化 BufferedStream 類的新執行個體。
本文轉自 qianshao 51CTO部落格,原文連結:http://blog.51cto.com/qianshao/210979,如需轉載請自行聯系原作者