MemoryStream和BufferedStream都派生自基類(lèi)Stream,因此它們有很多共同的屬性和方法,但是每一個(gè)類(lèi)都有自己獨(dú)特的用法。這兩個(gè)類(lèi)都是實(shí)現(xiàn)對(duì)內(nèi)存進(jìn)行數(shù)據(jù)讀寫(xiě)的功能,而不是對(duì)持久性存儲(chǔ)器進(jìn)行讀寫(xiě)。
讀寫(xiě)內(nèi)存-MemoryStream類(lèi)
MemoryStream類(lèi)用于向內(nèi)存而不是磁盤(pán)讀寫(xiě)數(shù)據(jù)。MemoryStream封裝以無(wú)符號(hào)字節(jié)數(shù)組形式存儲(chǔ)的數(shù)據(jù),該數(shù)組在創(chuàng)建MemoryStream對(duì)象時(shí)被初始化,或者該數(shù)組可創(chuàng)建為空數(shù)組??稍趦?nèi)存中直接訪問(wèn)這些封裝的數(shù)據(jù)。內(nèi)存流可降低應(yīng)用程序中對(duì)臨時(shí)緩沖區(qū)和臨時(shí)文件的需要。
下表列出了MemoryStream類(lèi)的重要方法:
1、Read():讀取MemoryStream流對(duì)象,將值寫(xiě)入緩存區(qū)。
2、ReadByte():從MemoryStream流中讀取一個(gè)字節(jié)。
3、Write():將值從緩存區(qū)寫(xiě)入MemoryStream流對(duì)象。
4、WriteByte():從緩存區(qū)寫(xiě)入MemoytStream流對(duì)象一個(gè)字節(jié)。
Read方法使用的語(yǔ)法如下:
mmstream.Read(byte[] buffer,offset,count)
其中mmstream為MemoryStream類(lèi)的一個(gè)流對(duì)象,3個(gè)參數(shù)中,buffer包含指定的字節(jié)數(shù)組,該數(shù)組中,從offset到(offset +count-1)之間的值由當(dāng)前流中讀取的字符替換。Offset是指Buffer中的字節(jié)偏移量,從此處開(kāi)始讀取。Count是指最多讀取的字節(jié)數(shù)。Write()方法和Read()方法具有相同的參數(shù)類(lèi)型。
MemoryStream類(lèi)的使用實(shí)例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace ConsoleApplication1 { class Program { static void Main() { int count; byte[] byteArray; char[] charArray; UnicodeEncoding uniEncoding = new UnicodeEncoding(); // Create the data to write to the stream. byte[] firstString = uniEncoding.GetBytes("一二三四五"); byte[] secondString = uniEncoding.GetBytes("上山打老虎"); using (MemoryStream memStream = new MemoryStream(100)) { // Write the first string to the stream. memStream.Write(firstString, 0, firstString.Length); // Write the second string to the stream, byte by byte. count = 0; while (count < secondString.Length) { memStream.WriteByte(secondString[count++]); } // Write the stream properties to the console. Console.WriteLine("Capacity={0},Length={1},Position={2}\n", memStream.Capacity.ToString(), memStream.Length.ToString(), memStream.Position.ToString()); // Set the position to the beginning of the stream. memStream.Seek(0, SeekOrigin.Begin); // Read the first 20 bytes from the stream. byteArray = new byte[memStream.Length]; count = memStream.Read(byteArray, 0, 20); // Read the remaining bytes, byte by byte. while (count < memStream.Length) { byteArray[count++] = Convert.ToByte(memStream.ReadByte()); } // Decode the byte array into a char array // and write it to the console. charArray = new char[uniEncoding.GetCharCount(byteArray, 0, count)]; uniEncoding.GetDecoder().GetChars(byteArray, 0, count, charArray, 0); Console.WriteLine(charArray); Console.ReadKey(); } } } }
在這個(gè)實(shí)例代碼中使用了using關(guān)鍵字。注意:
using 關(guān)鍵字有兩個(gè)主要用途:
1、作為指令,用于為命名空間創(chuàng)建別名或?qū)肫渌臻g中定義的類(lèi)型。
例如:
using System;
2、作為語(yǔ)句,用于定義一個(gè)范圍,在此范圍的末尾將釋放對(duì)象。
using(Connection conn=new Connection(connStr))
{
}
//使用using關(guān)鍵字可及時(shí)銷(xiāo)毀對(duì)象
MemoryStream.Capacity 屬性 取得或設(shè)定配置給這個(gè)資料流的位元組數(shù)目。
MemoryStream.Position 屬性 指定當(dāng)前流的位置。
MemoryStream.Length 屬性獲取用字節(jié)表示的流長(zhǎng)度。
SeekOrigin()是一個(gè)枚舉類(lèi),作用設(shè)定流的一個(gè)參數(shù)。
SeekOrigin.Begin我得理解就是文件的最開(kāi)始,“0”是偏移,表示跳過(guò)0個(gè)字節(jié)。寫(xiě)2就是跳過(guò)2個(gè)字節(jié)。
MemoryStream類(lèi)通過(guò)字節(jié)讀寫(xiě)數(shù)據(jù)。本例中定義了寫(xiě)入的字節(jié)數(shù)組,為了更好的說(shuō)明Write和WriteByte的異同,在代碼中聲明了兩個(gè)byte數(shù)組,其中一個(gè)數(shù)組寫(xiě)入時(shí)調(diào)用Write方法,通過(guò)指定該方法的三個(gè)參數(shù)實(shí)現(xiàn)如何寫(xiě)入。
另一個(gè)數(shù)組調(diào)用了WriteByte方法,每次寫(xiě)入一個(gè)字節(jié),所以采用while循環(huán)來(lái)完成全部字節(jié)的寫(xiě)入。寫(xiě)入MemoryStream后,可以檢索該流的容量,實(shí)際長(zhǎng)度,當(dāng)前流的位置,將這些值輸出到控制臺(tái)。通過(guò)觀察結(jié)果,可以確定寫(xiě)入MemoryStream流是否成功。
調(diào)用Read和ReadByte兩種方法讀取MemoryStream流中的數(shù)據(jù),并將其進(jìn)行Unicode編碼后輸出到控制臺(tái)。
讀取內(nèi)存流中的數(shù)據(jù)
在.NET中,使用抽象基類(lèi)System.IO.Stream代表流,它提供Read和Write兩個(gè)方法。由于數(shù)據(jù)流的有序性,因此流對(duì)象還有一個(gè)讀寫(xiě)指針,為此,Stream類(lèi)還有一個(gè)Seek方法用于移動(dòng)讀寫(xiě)指針。
字符串與字節(jié)數(shù)組間的互相轉(zhuǎn)化:
string str = "內(nèi)存大小"; byte[] temp = Encoding.UTF8.GetBytes (str); // 字符串轉(zhuǎn)化為字節(jié)數(shù)組 string s = Encoding.UTF8.GetString (temp); // 字節(jié)數(shù)組轉(zhuǎn)化為字符串 Debug.Log (s);
Encoding用法比較簡(jiǎn)單,如果只是字節(jié)和字符的互相轉(zhuǎn)換,GetBytes()和GetChars()這兩個(gè)方法及它們的重載基本上會(huì)滿(mǎn)足你所有要求。
GetByteCount()及其重載是得到一個(gè)字符串轉(zhuǎn)換成字節(jié)時(shí)實(shí)際的字節(jié)個(gè)數(shù)。
GetCharCount()及其重載是得到一個(gè)字節(jié)數(shù)組轉(zhuǎn)換成字符串的大小。
Decoder.GetChars 方法
Decoder.GetChars (Byte[], Int32, Int32, Char[], Int32)
在派生類(lèi)中重寫(xiě)時(shí),將指定字節(jié)數(shù)組的字節(jié)序列和內(nèi)部緩沖區(qū)中的任何字節(jié)解碼到指定的字符數(shù)組。
在派生類(lèi)中重寫(xiě)時(shí),將一個(gè)字節(jié)序列解碼為一組字符。
Java里一個(gè)byte取值范圍是-128~127, 而C#里一個(gè)byte是0~255.
首位不同. 但是底層I/O存儲(chǔ)的數(shù)據(jù)是一樣的
FileStream對(duì)象的數(shù)據(jù)來(lái)自文件,而MemoryStream對(duì)象的數(shù)據(jù)來(lái)自?xún)?nèi)存緩沖區(qū)。這兩個(gè)類(lèi)都繼承自Stream類(lèi)。
MemoryStream的數(shù)據(jù)來(lái)自?xún)?nèi)存中的一塊連續(xù)區(qū)域,這塊區(qū)域稱(chēng)為“緩沖區(qū)(Buffer)”。可以把緩沖區(qū)看成一個(gè)數(shù)組,每個(gè)數(shù)組元素可以存放一個(gè)字節(jié)的數(shù)據(jù)。
在創(chuàng)建MemoryStream對(duì)象時(shí),可以指定緩沖區(qū)的大小,并且可以在需要的時(shí)候更改。
//字節(jié)數(shù)組 byte[] buffer = new byte[600]; //填充字節(jié)數(shù)組 private void CreateExampleData() { for(int i=0; i<600; i++) { //byte類(lèi)型的數(shù)最大不能超過(guò)255,用256取模實(shí)現(xiàn) buffer[i] = (byte)(i%256); } }
內(nèi)存流的基本使用方法:
private void OnTestMemory() { //創(chuàng)建測(cè)試數(shù)據(jù) CreateExampleData(); //創(chuàng)建內(nèi)存流對(duì)象,初始分配50字節(jié)的緩沖區(qū) MemoryStream mem = new MemoryStream(50); //向內(nèi)存流中寫(xiě)入字節(jié)數(shù)組的所有數(shù)據(jù) mem.Write(buffer,0,buffer.GetLength(0)); MessageBox.Show("寫(xiě)入數(shù)據(jù)后的內(nèi)存流長(zhǎng)度:" + mem.Length.ToString()); MessageBox.Show("分配給內(nèi)存流的緩沖區(qū)大?。?quot; + mem.Capacity.ToString()); mem.SetLength(550); MessageBox.Show("調(diào)用SetLength方法后的內(nèi)存流長(zhǎng)度:" + mem.Length.ToString()); mem.Capacity = 620;//此值不能小于Length屬性 MessageBox.Show("調(diào)用Capacity方法后緩沖區(qū)大?。?quot; + mem.Capacity.ToString()); //將讀寫(xiě)指針移到距流開(kāi)頭10個(gè)字節(jié)的位置 mem.Seek(10,SeekOrigin.Begin); MessageBox.Show(mem.ReadByte().ToString()); mem.Close(); }
內(nèi)存流的Length屬性代表了其中存放的數(shù)據(jù)的真實(shí)長(zhǎng)度,而Capacity屬性則代表了分配給內(nèi)存流的內(nèi)存空間大小。
可以使用字節(jié)數(shù)組創(chuàng)建一個(gè)固定大小的MemoryStream,
MemoryStream mem = new MemoryStream(buffer);
這時(shí),無(wú)法再設(shè)置Capacity屬性的大小。
還可以創(chuàng)建只讀的內(nèi)存流對(duì)象。
MemoryStream mem = new MemoryStream(buffer,false);
FlieStream用于存取文件。
創(chuàng)建文件并寫(xiě)入內(nèi)容:
//創(chuàng)建一個(gè)新文件 FileStream fsForWrite = new FileStream("test.data",FileMode.Create); try { //寫(xiě)入一個(gè)字節(jié) fsForWrite.WriteByte(100); CreateExampleData(); //將字節(jié)數(shù)組寫(xiě)入文件 fsForWrite.Write(buffer,0,buffer.GetLength(0)); } catch(Exception ex) { MessageBox.Show(ex.Message); } finally { //關(guān)閉文件 fsForWrite.Close(); }
打開(kāi)文件并讀取內(nèi)容:
private void ReadFromFile() { FileStream fsForRead = new FileStream("test.data",FileMode.Open); try { //讀入一個(gè)字節(jié) MessageBox.Show("文件的第一個(gè)字節(jié)為:"+fsForRead.ReadByte().ToString()); //讀寫(xiě)指針移到距開(kāi)頭10個(gè)字節(jié)處 fsForRead.Seek(10,SeekOrigin.Begin); byte[] bs = new byte[10]; //從文件中讀取10個(gè)字節(jié)放到數(shù)組bs中 fsForRead.Read(bs,0,10); } catch(Exception ex) { MessageBox.Show(ex.Message); } finally { fsForRead.Close(); } }
如果一個(gè)程序退出了,但它打開(kāi)的文件沒(méi)有被關(guān)閉,將導(dǎo)致其他程序無(wú)法修改或刪除此文件。
FileStream與MemoryStream間的相互作用:
-----解決方案--------------------
FileStream fs = new FileStream(path, FileMode.Open); byte[] data = new byte[fs.Length]; fs.Read(data, 0, data.Length); fs.Close(); MemoryStream ms = new MemoryStream(data);
------解決方案--------------------
///定義并實(shí)例化一個(gè)內(nèi)存流,以存放圖片的字節(jié)數(shù)組。 MemoryStream m = new MemoryStream(); ///獲得當(dāng)前路徑 string strAppPath = AppDomain.CurrentDomain.BaseDirectory; //獲得可執(zhí)行文件的路徑。 ///獲得圖片路徑 string strPath = strAppPath + "img\\default.jpg"; ///圖片讀入FileStream FileStream f = new FileStream(strPath, FileMode.open); ///把FileStream寫(xiě)入MemoryStream m.SetLength(f.Length); f.Read(m.GetBuffer(), 0, (int)f.Length); m.Flush(); f.Close();
------解決方案--------------------
FileStream fs = new FileStream(fileName, FileMode.Open);
byte[] MyData = new byte[fs.Length];
fs.Read(MyData, 0, (int)fs.Length);
fs.Close();
MemoryStream ms = new MemoryStream(MyData);
------解決方案--------------------
MemoryStream ms = new MemoryStream(File.ReadAllBytes("c:\\1.jpg"));
另外在做BCP項(xiàng)目的時(shí)候,沒(méi)有遇到數(shù)據(jù)庫(kù),全部是從內(nèi)存取的數(shù)據(jù)
現(xiàn)提供從內(nèi)存取數(shù)據(jù)的方法:,這個(gè)是我從網(wǎng)上copy的
因?yàn)槿毡镜哪莻€(gè)項(xiàng)目,我們用的是c++程序讀寫(xiě)共有內(nèi)存,有一個(gè)c++寫(xiě)的dll文件
我們調(diào)用那個(gè)文件即可.
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace CrazyCoder.ShareMemLib { public class ShareMem { [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam); [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName); [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] public static extern IntPtr OpenFileMapping(int dwDesiredAccess,[MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,string lpName); [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] public static extern IntPtr MapViewOfFile(IntPtr hFileMapping,uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow,uint dwNumberOfBytesToMap); [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress); [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] public static extern bool CloseHandle(IntPtr handle); [DllImport("kernel32", EntryPoint="GetLastError")] public static extern int GetLastError (); const int ERROR_ALREADY_EXISTS = 183; const int FILE_MAP_COPY = 0x0001; const int FILE_MAP_WRITE = 0x0002; const int FILE_MAP_READ = 0x0004; const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004; const int PAGE_READONLY = 0x02; const int PAGE_READWRITE = 0x04; const int PAGE_WRITECOPY = 0x08; const int PAGE_EXECUTE = 0x10; const int PAGE_EXECUTE_READ = 0x20; const int PAGE_EXECUTE_READWRITE = 0x40; const int SEC_COMMIT = 0x8000000; const int SEC_IMAGE = 0x1000000; const int SEC_NOCACHE = 0x10000000; const int SEC_RESERVE = 0x4000000; const int INVALID_HANDLE_VALUE = -1; IntPtr m_hSharedMemoryFile = IntPtr.Zero; IntPtr m_pwData = IntPtr.Zero; bool m_bAlreadyExist = false; bool m_bInit = false; long m_MemSize=0; public ShareMem() { } ~ShareMem() { Close(); } /// /// 初始化共享內(nèi)存 /// /// 共享內(nèi)存名稱(chēng) /// 共享內(nèi)存大小 /// public int Init(string strName, long lngSize) { if (lngSize <= 0 || lngSize > 0x00800000) lngSize = 0x00800000; m_MemSize = lngSize; if (strName.Length > 0) { //創(chuàng)建內(nèi)存共享體(INVALID_HANDLE_VALUE) m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)lngSize, strName); if (m_hSharedMemoryFile == IntPtr.Zero) { m_bAlreadyExist = false; m_bInit = false; return 2; //創(chuàng)建共享體失敗 } else { if (GetLastError() == ERROR_ALREADY_EXISTS) //已經(jīng)創(chuàng)建 { m_bAlreadyExist = true; } else //新創(chuàng)建 { m_bAlreadyExist = false; } } //--------------------------------------- //創(chuàng)建內(nèi)存映射 m_pwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_WRITE, 0, 0, (uint)lngSize); if (m_pwData == IntPtr.Zero) { m_bInit = false; CloseHandle(m_hSharedMemoryFile); return 3; //創(chuàng)建內(nèi)存映射失敗 } else { m_bInit = true; if (m_bAlreadyExist == false) { //初始化 } } //---------------------------------------- } else { return 1; //參數(shù)錯(cuò)誤 } return 0; //創(chuàng)建成功 } /// /// 關(guān)閉共享內(nèi)存 /// public void Close() { if (m_bInit) { UnmapViewOfFile(m_pwData); CloseHandle(m_hSharedMemoryFile); } } /// /// 讀數(shù)據(jù) /// /// 數(shù)據(jù) /// 起始地址 /// 個(gè)數(shù) /// public int Read(ref byte[] bytData, int lngAddr, int lngSize) { if (lngAddr + lngSize > m_MemSize) return 2; //超出數(shù)據(jù)區(qū) if (m_bInit) { Marshal.Copy(m_pwData, bytData, lngAddr, lngSize); } else { return 1; //共享內(nèi)存未初始化 } return 0; //讀成功 } /// /// 寫(xiě)數(shù)據(jù) /// /// 數(shù)據(jù) /// 起始地址 /// 個(gè)數(shù) /// public int Write(byte[] bytData, int lngAddr, int lngSize) { if (lngAddr + lngSize > m_MemSize) return 2; //超出數(shù)據(jù)區(qū) if (m_bInit) { Marshal.Copy(bytData, lngAddr, m_pwData, lngSize); } else { return 1; //共享內(nèi)存未初始化 } return 0; //寫(xiě)成功 } } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using ShareMemLib; namespace YFShareMem { public partial class frmShareMem : Form { ShareMem MemDB=new ShareMem(); public frmShareMem() { InitializeComponent(); } private void btnOpen_Click(object sender, EventArgs e) { if (MemDB.Init("YFMemTest", 10240) != 0) { //初始化失敗 MessageBox.Show("初始化失敗"); } else { btnOpen.Enabled = false; chkWrite.Enabled = true; tmrTime.Enabled = true; } } private void tmrTime_Tick(object sender, EventArgs e) { byte[] bytData = new byte[16]; int intRet = MemDB.Read(ref bytData, 0, 16); lstData.Items.Clear(); if (intRet == 0) { for (int i = 0; i < 16; i++) { lstData.Items.Add(bytData[i].ToString()); } if (chkWrite.Checked) { bytData[0]++; bytData[1] += 2; if (bytData[0] > 200) bytData[0] = 0; if (bytData[1] > 200) bytData[1] = 0; MemDB.Write(bytData, 0, 16); } } } } }
如對(duì)本文有疑問(wèn),請(qǐng)?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會(huì)為你解答?。?點(diǎn)擊進(jìn)入論壇