把握VB.NET中的流FileStream

來源:互聯網
上載者:User
stream 當你第一次用VB.NET讀寫檔案的時候,你肯定會發現VB.NET摒棄了傳統的檔案I/O支援,感覺不習慣。其實,在.NET裡面,微軟用豐富的“流”對象取代了傳統的檔案操作,而“流”,是一個在Unix裡面經常使用的對象. 我們可以把流當作一個通道,程式的的資料可以沿著這個通道”流”到各種資料存放區機構(比如:檔案,字串,數組,或者其他形式的流等)。為什麼我們會摒棄用了那麼久的IO操作,而代之為流呢?其中很重要的一個原因就是並不是所有的資料都存在於檔案中。現在的程式,從各種類型的資料存放區中擷取資料,比如可以是一個檔案,記憶體中的緩衝區,還有InterneT。而流技術使得應用程式能夠基於一個編程模型,擷取各種資料,而不必要學會怎麼樣去擷取遠程web伺服器上的一個檔案的具體技術。我們只需要在應用程式和web伺服器之間建立一個流,然後讀取伺服器發送的資料就可以了。  流對象,封裝了讀寫資料來源的各種操作,最大的優點就是一當你學好怎麼樣操作某一個資料來源時,你就可以把這種技術擴充到其他形形色色的資料來源。 流的種類流是一個抽象類別,你不能在程式中申明Stream的一個執行個體。在.NET裡面,由Stream派生出5種具體的流,分別是

FileStream       支援對檔案的順序和隨機讀寫操作MemoryStream   支援對記憶體緩衝區的順序和隨機讀寫操作NETworkStream  支援對Internet網路資源的順序和隨機讀寫操作,存在於System.Net.Sockets名稱空間CryptoStream    支援資料的編碼和解碼,存在於System.Security.Cryptography 名稱空間BufferedStream  支援緩衝式的讀寫對那些本身不支援的對象   並不是所有的Stream都採用用完全一摸一樣的方法,比如讀取本地檔案的流,可以告訴我們檔案的長度,當前讀寫的位置等,你可以用Seek方法跳到檔案的任意位置。相反,讀取遠程檔案的流不支援這些特性。不過,Stream本身有CanSeek, CanRead 和 CanWrite屬性,用於區別資料來源,告訴我們支援還是不支援某中特性。  下面我們簡單介紹一個FileStream類 FileStream類 進行本地檔案操作的時候,我們可以採用FileSteam類, 可以很簡單的讀寫為位元組數組(arrays of bytes)。對於單一資料型別的資料的讀寫,可以採用BinaryReader 和BinaryWriter以及StreamReader,StreamWriter類。 BinaryReader,用特定的編碼將基中繼資料類型讀作二進位值。BinaryWriter以二進位形式將基元類型寫入流,並支援用特定的編碼寫入字串。StreamReader/Writer則是把資料存放區為XML格式。在VB.NET裡面採用那個區別不大,因為所用的類都應用於兩種格式。VB.NET支援傳統的隨機讀寫檔案,你可以建立檔案,用於儲存Struct,然後根據記錄數訪問。就像在以前的Vb版本中一樣,用FileOpen,FileGet函數。很大程度上,這已經被XML或者資料庫取代。如果你建立新的應用程式,而有不需要考慮跟就版本的相容問題,建議採用.NET的新特性。不管你將要使用拿一個StreamClass,你都必須建立一個FileStream對象。有很多方式建立,最簡單就是指定檔案路徑,開啟模式,如下面的文法。 Dim fStream As New FileStream(path, fileMode, fileAccess)Path要包含檔案的路徑以及檔案名稱。fileMode是枚舉類型FileMode的成員之一,如下表所示。fileAccess是枚舉類型FileAccess的成員。Read (唯讀), ReadWrite (讀寫), and Write (寫操作)。決定了檔案的讀寫權限。  

成員名稱 說明
Append 開啟現有檔案並尋找到檔案尾,或建立新檔案。
Create 指定作業系統應建立新檔案。如果檔案已存在,它將被改寫。
CreateNew 指定作業系統應建立新檔案。
Open 指定作業系統應開啟現有檔案。
OpenOrCreate 指定作業系統應開啟檔案(如果檔案存在);否則,應建立新檔案。
Truncate 指定作業系統應開啟現有檔案。檔案一旦開啟,就將被截斷為為零位元組大小。

 當然,你也可以用 (Open,  OpenRead,  OpenText, OpenWrite)建立FileStream  Dim FS As New FileStream = IO.File.OpenWrite("c:\Stream.txt") 另外一種方式開啟檔案可以用OpenFileDialog 和 SaveFileDialog控制項的OpenFile方法。不需要指定任何參數。 OpenFileDialog的OpenFile方法以唯讀方式開啟檔案; SaveFileDialog的OpenFile方法以讀寫方式開啟檔案。 FileStream只支援最基本的操作,把資料寫入位元組數組或者從位元組數組寫入檔案中。如果我們用FileStream把資料儲存在檔案中,首先把資料轉化為Byte數組,然後調用FileStream的Write方法。同樣,FileStream的Read方法,返回的也是位元組數組。你或許不會經常直接使用FileStream對象,我們還是有必要簡單看一下它的準系統建立FileStream對象之後,調用WriteByte 寫一個位元組到檔案中。 Write方法可以將一個數組寫入檔案中,需要三個參數   Write(buffer, offset, count)Buffer是要寫入數組地址,offset是位移量,count指寫入位元組數量,Read的文法也一樣。 由於FileStream要跟Bytes Array打交道,所以研究一下ASCIIEncoding 的GetBytes和UnicodeEncoding 的GetChars很有必要 下面的例子是一個轉換操作。   Dim buffer() As Byte   Dim encoder As New System.Text.ASCIIEncoding()   Dim str As String = "This is a line of text"   ReDim buffer(str.Length - 1)   Encoder.GetBytes(str, 0, str.Length, buffer, 0)   FS.Write(buffer, 0, buffer.Length) 注意:必須Resize要寫入的Byte數組為要讀寫的長度。
靈活多樣的 IO 操作 有時候,在資料和位元組數組之間轉換是一件繁瑣的事情。為了避免這些無聊的轉換和簡化代碼,採用StreamReader/StreamWrite和BinaryReader/BinaryWriter不愧為明智之舉。StreamReader/StreamWrite分別由TextReader/TextWriter類派生,自動執行位元組編碼的轉換。BinaryReader/BinaryWriter由Stream派生,主要以二進位的形式讀寫資料。從二進位檔案讀資料的時候,首先建立一個BinaryReader的執行個體,BinaryReader的構建函數接受一個FileStream對象,代表將要讀的檔案。我們前面已經看過,可以用 File.OpenRead 或者 File.OpenWrite 方法建立FileStream對象。如下所示:   Dim BR As New IO.BinaryReader(IO.File.OpenRead(path))   Dim BW As New IO.BinaryWriter(IO.File.OpenWrite(path))            BinaryWriter類有 WriteWriteLine兩種方法,都可以接受任何類型的資料作為參數寫入檔案( WriteLine在檔案尾追加一行資料)。BinaryReader類有很多讀資料的方法,資料存放區在檔案上的時候,並沒有任何關於自己類型的資訊,所以讀資料的時候,必須選擇合適的重載Read方法。            下面的例子假設BW是一個已經初始化過的BinaryWriter對象,表示如何寫一個字串、整數、雙精確度數字到檔案:   BW.WriteLine("A String")   BW.WriteLine(12345)   BW.WriteLine(123.456789999999)         讀回資料的時候,必須選擇BinaryReader合適的Read方法:   Dim s As String = BR.ReadString()   Dim i As Int32 = BR.ReadInt32()   Dim dbl As Double = BR.ReadDouble()對於文字檔,採用StreamReader/StreamWriter對象。方法跟上面差不多,寫資料同樣用Write和WriteLine方法。Read方法讀一個字元,ReadLine讀一行資料(直到有斷行符號/分行符號為止),ReadToEnd讀所有的字元,到檔案結束。

對象序列化 到目前為止,我們只是把簡單類型的資料寫到檔案中並讀回程式。而實際上,大多數的程式讀寫的資料可能並不是簡單類型,而是複雜的結構,例如:數組,數組列表,雜湊表等。於是,我們採取一種成為序列化的技術,首先把數組的值轉化為位元組序列,然後寫入檔案,這樣整個數組就儲存下來。相反,我們稱之為還原序列化。序列化是.NET的一個很大的話題,這列介紹一下基本的資訊。用BinaryFormatter的 SerializeDeserialize方法把一個對象儲存到檔案和讀回程式。首先,imports System.RunTime.Serialization.Formatters,免得寫那麼長的申明。Formatters名空間包含了BinaryFormatter類,用於以二進位的資料序列化對象。建立BinaryFormatter執行個體,接著調用 Serialize方法, Serialize接受兩個參數:一個是可寫的FileStream執行個體,用於儲存資料的檔案;另外一個是對象本身:   Dim BinFormatter As New Binary.BinaryFormatter()   Dim R As New Rectangle(10, 20, 100, 200)   BinFormatter.Serialize(FS, R)         BinaryFormatter的 Deserialize方法只有一個參數,FileStream執行個體。在當前位置,還原序列化得到一個類型不明的對象,我們必須用Ctype轉換為原來的對象。下面的例子還原序列化上面的檔案得到原來的Rectangle對象:   Dim R As New Rectangle()   R = CType(BinFormatter.Deserialize(FS), Rectangle)我們也可以以XmlFormatter進行對象序列化。首先在IDE的Project菜單選擇添加System.Runtime.Serialization.Formatters.Soap,然後就可以進行建立SoapFormatter對象了,方法跟BinFormatter一樣,只不過資料的儲存採用XML格式:   Dim FS As New IO.FileStream("c:\Rect.xml", IO.FileMode.Create, IO.FileAccess.Write)   Dim XMLFormatter As New SoapFormatter()   Dim R As New Rectangle(8, 8, 299, 499)   XMLFormatter.Serialize(FS, R)開啟c:\Rect.xml ,實際上裡面儲存了這些內容:  - <SOAP-ENV:Envelope xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd=" http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC=" http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV=" http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr=" http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle=" http://schemas.xmlsoap.org/soap/encoding/"> - <SOAP-ENV:Body> - <a1:Rectangle id=" ref-1" xmlns:a1=" http://schemas.microsoft.com/clr/nsassem/System.Drawing/System.Drawing%2C%20Version%3D1.0.3300.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db03f5f7f11d50a3a">   <x> 8</x>   <y> 8</y>   <width> 249</width>   <height> 499</height>   </a1:Rectangle>   </SOAP-ENV:Body>   </SOAP-ENV:Envelope>

檔案操作具體執行個體 在這一部分,你將找到更多常用的檔案操作的代碼執行個體。最常用、最基本的操作就是把text寫入檔案和讀回來。現在的應用程式通常不用二進位檔案作儲存簡單的變數,而用它來儲存物件,對象集合以及其他機器代碼。下面,將看到具體操作的例子。 讀寫文字檔 為了把text儲存到檔案,建立一個基於FileStream的StreamReader對象,然後調用Write方法把需要儲存的text寫入檔案。下面的代碼用SaveFileDialog提示使用者指定一個檔案,用於儲存TextBox1的內容。    SaveFileDialog1.Filter = _      "Text Files|*.txt|All Files|*.*"   SaveFileDialog1.FilterIndex = 0   If SaveFileDialog1.ShowDialog = DialogResult.OK Then       Dim FS As FileStream = SaveFileDialog1.OpenFile       Dim SW As New StreamWriter(FS)       SW.Write(TextBox1.Text)       SW.Close()       FS.Close()   End If 同樣採用類似的語句,我們讀取一個文字檔,並把內容顯示在TextBox控制項中。StreamReader的ReadToEnd方法返迴文件的全部內容。    OpenFileDialog1.Filter = _      "Text Files|*.txt|All Files|*.*"   OpenFileDialog1.FilterIndex = 0   If OpenFileDialog1.ShowDialog = DialogResult.OK Then       Dim FS As FileStream       FS = OpenFileDialog1.OpenFile       Dim SR As New StreamReader(FS)       TextBox1.Text = SR.ReadToEnd       SR.Close()       FS.Close()   End If 各種對象的儲存 採用BinaryFormatte以二進位的形式,或者用SoapFormatter類以XML格式都可以序列化一個具體的對象。只要把所有BinaryFormatter的引用改為SoapFormatter,無需改變任何代碼,就可以以XML格式序列化對象。首先建立一個BinaryFormatter執行個體:   Dim BinFormatter As New Binary.BinaryFormatter()然後建立一個用於儲存序列化對象的FileStream對象:   Dim FS As New System.IO.FileStream("c:\test.txt", IO.FileMode.Create) 接著調用BinFormatter的 Serialize方法序列化任何可以序列化的framework對象:   R = New Rectangle(rnd.Next(0, 100),rnd.Next(0, 300), _         rnd.Next(10, 40),rnd.Next(1, 9))   BinFormatter.Serialize(FS, R) 加一個Serializable屬性使得自訂的對象可以序列化    <Serializable()> Public Structure Person       Dim Name As String       Dim Age As Integer       Dim Income As Decimal   End Structure 下面代碼建立一個Person對象執行個體,然後調用BinFormatter的 Serialize方法序列化自訂對象:   P = New Person()   P.Name = "Joe Doe"   P.Age = 35   P.Income = 28500   BinFormatter.Serialize(FS, P)你也可以在同一個Stream中接著序列化其他對象,然後以同樣的順序讀回。例如,在序列化Person對象之後接著序列化一個Rectangle對象:   BinFormatter.Serialize(FS, New Rectangle(0, 0, 100, 200))     建立一個BinaryFormatter對象,調用其 Deserialize方法,然後把返回的值轉化為正確的類型,就是整個還原序列化過程。然後接著發序列化Stream的其他對象。假定已經序列化了Person和Rectangle兩個對象,以同樣的順序,我們還原序列化就可以得到原來的對象:

    Dim P As New Person()   P = BinFormatter.Serialize(FS, Person)   Dim R As New Rectangle   R = BinFormatter.Serialize(FS, Rectangle) Persisting Collections 集合的儲存 大多數程式處理對象集合而不是單個的對象。對於集合資料,首先建立一個數組(或者是其他類型的集合,比如ArrayList或HashTable),用對象填充,然後一個Serialize方法就可以序列化真箇集合,是不是很簡單?下面的例子,首先建立一個有兩個Person對象的ArrayList,然後序列化本身:

    Dim FS As New System.IO.FileStream _      ("c:\test.txt", IO.FileMode.Create)   Dim BinFormatter As New Binary.BinaryFormatter()   Dim P As New Person()   Dim Persons As New ArrayList   P = New Person()   P.Name = "Person 1"   P.Age = 35   P.Income = 32000   Persons.Add(P)      P = New Person()   P.Name = "Person 2"   P.Age = 50   P.Income = 72000   Persons.Add(P)      BinFormatter.Serialize(FS, Persons)以儲存序列化資料的檔案為參數,調用一個BinaryFormatter執行個體的 Deserialize方法,就會返回一個對象,然後把它轉化為合適的類型。下面的代碼還原序列化檔案中的所有對象,然後處理所有的Person對象:    FS = New System.IO.FileStream _      ("c:\test.txt", IO.FileMode.OpenOrCreate)   Dim obj As Object   Dim P As Person(), R As Rectangle()   Do       obj = BinFormatter.Deserialize(FS)       If obj.GetType Is GetType(Person) Then           P = CType(obj, Person)           ' Process the P objext       End If   Loop While FS.Position < FS.Length - 1   FS.Close()下面的例子調用Deserialize方法還原序列化真箇集合,然後把傳回值轉換為合適的類型(Person):   FS = New System.IO.FileStream("c:\test.txt", IO.FileMode.OpenOrCreate)   Dim obj As Object   Dim Persons As New ArrayList   obj = CType(BinFormatter.Deserialize(FS), ArrayList)   FS.Close()


相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。