国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

把握VB.NET中的流FileStream

2024-07-10 13:07:10
字體:
供稿:網(wǎng)友
當(dāng)你第一次用vb.net讀寫文件的時(shí)候,你肯定會(huì)發(fā)現(xiàn)vb.net摒棄了傳統(tǒng)的文件i/o支持,感覺不習(xí)慣。其實(shí),在.net里面,微軟用豐富的“流”對(duì)象取代了傳統(tǒng)的文件操作,而“流”,是一個(gè)在unix里面經(jīng)常使用的對(duì)象. 我們可以把流當(dāng)作一個(gè)通道,程序的的數(shù)據(jù)可以沿著這個(gè)通道”流”到各種數(shù)據(jù)存儲(chǔ)機(jī)構(gòu)(比如:文件,字符串,數(shù)組,或者其他形式的流等)。為什么我們會(huì)摒棄用了那么久的io操作,而代之為流呢?其中很重要的一個(gè)原因就是并不是所有的數(shù)據(jù)都存在于文件中。現(xiàn)在的程序,從各種類型的數(shù)據(jù)存儲(chǔ)中獲取數(shù)據(jù),比如可以是一個(gè)文件,內(nèi)存中的緩沖區(qū),還有internet。而流技術(shù)使得應(yīng)用程序能夠基于一個(gè)編程模型,獲取各種數(shù)據(jù),而不必要學(xué)會(huì)怎么樣去獲取遠(yuǎn)程web服務(wù)器上的一個(gè)文件的具體技術(shù)。我們只需要在應(yīng)用程序和web服務(wù)器之間創(chuàng)建一個(gè)流,然后讀取服務(wù)器發(fā)送的數(shù)據(jù)就可以了。 
流對(duì)象,封裝了讀寫數(shù)據(jù)源的各種操作,最大的優(yōu)點(diǎn)就是一當(dāng)你學(xué)好怎么樣操作某一個(gè)數(shù)據(jù)源時(shí),你就可以把這種技術(shù)擴(kuò)展到其他形形色色的數(shù)據(jù)源。 
流的種類
流是一個(gè)抽象類,你不能在程序中申明stream的一個(gè)實(shí)例。在.net里面,由stream派生出5種具體的流,分別是

filestream       支持對(duì)文件的順序和隨機(jī)讀寫操作
memorystream   支持對(duì)內(nèi)存緩沖區(qū)的順序和隨機(jī)讀寫操作
networkstream  支持對(duì)internet網(wǎng)絡(luò)資源的順序和隨機(jī)讀寫操作,存在于system.net.sockets名稱空間
cryptostream    支持?jǐn)?shù)據(jù)的編碼和解碼,存在于system.security.cryptography 名稱空間
bufferedstream  支持緩沖式的讀寫對(duì)那些本身不支持的對(duì)象
 
 
并不是所有的stream都采用用完全一摸一樣的方法,比如讀取本地文件的流,可以告訴我們文件的長度,當(dāng)前讀寫的位置等,你可以用seek方法跳到文件的任意位置。相反,讀取遠(yuǎn)程文件的流不支持這些特性。不過,stream本身有canseek, canread 和 canwrite屬性,用于區(qū)別數(shù)據(jù)源,告訴我們支持還是不支持某中特性。
 
下面我們簡單介紹一個(gè)filestream類
 
filestream類
 
進(jìn)行本地文件操作的時(shí)候,我們可以采用filesteam類, 可以很簡單的讀寫為字節(jié)數(shù)組(arrays of bytes)。對(duì)于簡單數(shù)據(jù)類型的數(shù)據(jù)的讀寫,可以采用binaryreader 和binarywriter以及streamreader,streamwriter類。 binaryreader,用特定的編碼將基元數(shù)據(jù)類型讀作二進(jìn)制值。binarywriter以二進(jìn)制形式將基元類型寫入流,并支持用特定的編碼寫入字符串。streamreader/writer則是把數(shù)據(jù)存儲(chǔ)為xml格式。在vb.net里面采用那個(gè)區(qū)別不大,因?yàn)樗玫念惗紤?yīng)用于兩種格式。
vb.net支持傳統(tǒng)的隨機(jī)讀寫文件,你可以創(chuàng)建文件,用于存儲(chǔ)struct,然后根據(jù)記錄數(shù)訪問。就像在以前的vb版本中一樣,用fileopen,fileget函數(shù)。很大程度上,這已經(jīng)被xml或者數(shù)據(jù)庫取代。如果你創(chuàng)建新的應(yīng)用程序,而有不需要考慮跟就版本的兼容問題,建議采用.net的新特性。
不管你將要使用拿一個(gè)streamclass,你都必須創(chuàng)建一個(gè)filestream對(duì)象。有很多方式創(chuàng)建,最簡單就是指定文件路徑,打開模式,如下面的語法。
 dim fstream as new filestream(path, filemode, fileaccess)
path要包含文件的路徑以及文件名。filemode是枚舉類型filemode的成員之一,如下表所示。fileaccess是枚舉類型fileaccess的成員。read (只讀), readwrite (讀寫), and write (寫操作)。決定了文件的讀寫權(quán)限。
 

成員名稱
說明
append
打開現(xiàn)有文件并查找到文件尾,或創(chuàng)建新文件。
create
指定操作系統(tǒng)應(yīng)創(chuàng)建新文件。如果文件已存在,它將被改寫。
createnew
指定操作系統(tǒng)應(yīng)創(chuàng)建新文件。
open
指定操作系統(tǒng)應(yīng)打開現(xiàn)有文件。
openorcreate
指定操作系統(tǒng)應(yīng)打開文件(如果文件存在);否則,應(yīng)創(chuàng)建新文件。
truncate
指定操作系統(tǒng)應(yīng)打開現(xiàn)有文件。文件一旦打開,就將被截?cái)酁闉榱阕止?jié)大小。

 
當(dāng)然,你也可以用 (open,  openread,  opentext, openwrite)創(chuàng)建filestream
 
dim fs as new filestream = io.file.openwrite("c:/stream.txt")
 
另外一種方式打開文件可以用openfiledialog 和 savefiledialog控件的openfile方法。
不需要指定任何參數(shù)。 openfiledialog的openfile方法以只讀方式打開文件; savefiledialog的openfile方法以讀寫方式打開文件。
 
filestream只支持最基本的操作,把數(shù)據(jù)寫入字節(jié)數(shù)組或者從字節(jié)數(shù)組寫入文件中。如果我們用filestream把數(shù)據(jù)保存在文件中,首先把數(shù)據(jù)轉(zhuǎn)化為byte數(shù)組,然后調(diào)用filestream的write方法。同樣,filestream的read方法,返回的也是字節(jié)數(shù)組。你或許不會(huì)經(jīng)常直接使用filestream對(duì)象,我們還是有必要簡單看一下它的基本功能
創(chuàng)建filestream對(duì)象之后,調(diào)用writebyte 寫一個(gè)字節(jié)到文件中。 write方法可以將一個(gè)數(shù)組寫入文件中,需要三個(gè)參數(shù)
   write(buffer, offset, count)
buffer是要寫入數(shù)組地址,offset是偏移量,count指寫入字節(jié)數(shù)量,read的語法也一樣。
 
由于filestream要跟bytes array打交道,所以研究一下asciiencoding 的getbytes和unicodeencoding 的getchars很有必要
 
下面的例子是一個(gè)轉(zhuǎn)換操作。
   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數(shù)組為要讀寫的長度。
靈活多樣的io操作
有時(shí)候,在數(shù)據(jù)和字節(jié)數(shù)組之間轉(zhuǎn)換是一件繁瑣的事情。為了避免這些無聊的轉(zhuǎn)換和簡化代碼,采用streamreader/streamwritebinaryreader/binarywriter不愧為明智之舉。streamreader/streamwrite分別由textreader/textwriter類派生,自動(dòng)執(zhí)行字節(jié)編碼的轉(zhuǎn)換。binaryreader/binarywriterstream派生,主要以二進(jìn)制的形式讀寫數(shù)據(jù)。
從二進(jìn)制文件讀數(shù)據(jù)的時(shí)候,首先創(chuàng)建一個(gè)binaryreader的實(shí)例,binaryreader的構(gòu)建函數(shù)接受一個(gè)filestream對(duì)象,代表將要讀的文件。我們前面已經(jīng)看過,可以用file.openread 或者 file.openwrite 方法創(chuàng)建filestream對(duì)象。
如下所示:
   dim br as new io.binaryreader(io.file.openread(path))
   dim bw as new io.binarywriter(io.file.openwrite(path))
            binarywriter類有writewriteline兩種方法,都可以接受任何類型的數(shù)據(jù)作為參數(shù)寫入文件(writeline在文件尾追加一行數(shù)據(jù))。binaryreader類有很多讀數(shù)據(jù)的方法,數(shù)據(jù)存儲(chǔ)在文件上的時(shí)候,并沒有任何關(guān)于自己類型的信息,所以讀數(shù)據(jù)的時(shí)候,必須選擇合適的重載read方法。
            下面的例子假設(shè)bw是一個(gè)已經(jīng)初始化過的binarywriter對(duì)象,表示如何寫一個(gè)字符串、整數(shù)、雙精度數(shù)字到文件:
   bw.writeline("a string")
   bw.writeline(12345)
   bw.writeline(123.456789999999)
         讀回?cái)?shù)據(jù)的時(shí)候,必須選擇binaryreader合適的read方法:
   dim s as string = br.readstring()
   dim i as int32 = br.readint32()
   dim dbl as double = br.readdouble()
對(duì)于文本文件,采用streamreader/streamwriter對(duì)象。方法跟上面差不多,寫數(shù)據(jù)同樣用writewriteline方法。read方法讀一個(gè)字符,readline讀一行數(shù)據(jù)(直到有回車/換行符為止),readtoend讀所有的字符,到文件結(jié)束。

對(duì)象序列化
到目前為止,我們只是把簡單類型的數(shù)據(jù)寫到文件中并讀回程序。而實(shí)際上,大多數(shù)的程序讀寫的數(shù)據(jù)可能并不是簡單類型,而是復(fù)雜的結(jié)構(gòu),例如:數(shù)組,數(shù)組列表,哈希表等。于是,我們采取一種成為序列化的技術(shù),首先把數(shù)組的值轉(zhuǎn)化為字節(jié)序列,然后寫入文件,這樣整個(gè)數(shù)組就存儲(chǔ)下來。相反,我們稱之為反序列化。
序列化是.net的一個(gè)很大的話題,這列介紹一下基本的信息。
binaryformatterserialize deserialize方法把一個(gè)對(duì)象保存到文件和讀回程序。首先,imports system.runtime.serialization.formatters,免得寫那么長的申明。formatters名空間包含了binaryformatter類,用于以二進(jìn)制的數(shù)據(jù)序列化對(duì)象。
創(chuàng)建binaryformatter實(shí)例,接著調(diào)用serialize方法,serialize接受兩個(gè)參數(shù):一個(gè)是可寫的filestream實(shí)例,用于保存數(shù)據(jù)的文件;另外一個(gè)是對(duì)象本身:
   dim binformatter as new binary.binaryformatter()
   dim r as new rectangle(10, 20, 100, 200)
   binformatter.serialize(fs, r)
         binaryformatterdeserialize方法只有一個(gè)參數(shù),filestream實(shí)例。在當(dāng)前位置,反序列化得到一個(gè)類型不明的對(duì)象,我們必須用ctype轉(zhuǎn)換為原來的對(duì)象。下面的例子反序列化上面的文件得到原來的rectangle對(duì)象:
   dim r as new rectangle()
   r = ctype(binformatter.deserialize(fs), rectangle)
我們也可以以xmlformatter進(jìn)行對(duì)象序列化。首先在ideproject菜單選擇添加system.runtime.serialization.formatters.soap,然后就可以進(jìn)行創(chuàng)建soapformatter對(duì)象了,方法跟binformatter一樣,只不過數(shù)據(jù)的存儲(chǔ)采用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 ,實(shí)際上里面存儲(chǔ)了這些內(nèi)容:
 
- <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>

文件操作具體實(shí)例
在這一部分,你將找到更多常用的文件操作的代碼實(shí)例。最常用、最基本的操作就是把text寫入文件和讀回來。現(xiàn)在的應(yīng)用程序通常不用二進(jìn)制文件作存儲(chǔ)簡單的變量,而用它來存儲(chǔ)對(duì)象,對(duì)象集合以及其他機(jī)器代碼。下面,將看到具體操作的例子。
讀寫文本文件
為了把text保存到文件,創(chuàng)建一個(gè)基于filestream的streamreader對(duì)象,然后調(diào)用write方法把需要保存的text寫入文件。下面的代碼用savefiledialog提示用戶指定一個(gè)文件,用于保存textbox1的內(nèi)容。
 
   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
 
同樣采用類似的語句,我們讀取一個(gè)文本文件,并把內(nèi)容顯示在textbox控件中。streamreader的readtoend方法返回文件的全部內(nèi)容。
 
   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
各種對(duì)象的存儲(chǔ)
采用binaryformatte以二進(jìn)制的形式,或者用soapformatter類以xml格式都可以序列化一個(gè)具體的對(duì)象。只要把所有binaryformatter的引用改為soapformatter,無需改變?nèi)魏未a,就可以以xml格式序列化對(duì)象。
首先創(chuàng)建一個(gè)binaryformatter實(shí)例:
   dim binformatter as new binary.binaryformatter()
然后創(chuàng)建一個(gè)用于存儲(chǔ)序列化對(duì)象的filestream對(duì)象:
   dim fs as new system.io.filestream("c:/test.txt", io.filemode.create)
 
接著調(diào)用binformatter的serialize方法序列化任何可以序列化的framework對(duì)象:
   r = new rectangle(rnd.next(0, 100),rnd.next(0, 300), _
         rnd.next(10, 40),rnd.next(1, 9))
   binformatter.serialize(fs, r)
 
加一個(gè)serializable屬性使得自定義的對(duì)象可以序列化
 
   <serializable()> public structure person
       dim name as string
       dim age as integer
       dim income as decimal
   end structure
 
下面代碼創(chuàng)建一個(gè)person對(duì)象實(shí)例,然后調(diào)用binformatter的serialize方法序列化自定義對(duì)象:
   p = new person()
   p.name = "joe doe"
   p.age = 35
   p.income = 28500
   binformatter.serialize(fs, p)
你也可以在同一個(gè)stream中接著序列化其他對(duì)象,然后以同樣的順序讀回。例如,在序列化person對(duì)象之后接著序列化一個(gè)rectangle對(duì)象:
   binformatter.serialize(fs, new rectangle(0, 0, 100, 200))
     創(chuàng)建一個(gè)binaryformatter對(duì)象,調(diào)用其deserialize方法,然后把返回的值轉(zhuǎn)化為正確的類型,就是整個(gè)反序列化過程。然后接著發(fā)序列化stream的其他對(duì)象。
假定已經(jīng)序列化了person和rectangle兩個(gè)對(duì)象,以同樣的順序,我們反序列化就可以得到原來的對(duì)象:

 
   dim p as new person()
   p = binformatter.serialize(fs, person)
   dim r as new rectangle
   r = binformatter.serialize(fs, rectangle)
persisting collections
集合的存儲(chǔ)
大多數(shù)程序處理對(duì)象集合而不是單個(gè)的對(duì)象。對(duì)于集合數(shù)據(jù),首先創(chuàng)建一個(gè)數(shù)組(或者是其他類型的集合,比如arraylist或hashtable),用對(duì)象填充,然后一個(gè)serialize方法就可以序列化真?zhèn)€集合,是不是很簡單?下面的例子,首先創(chuàng)建一個(gè)有兩個(gè)person對(duì)象的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)
以存儲(chǔ)序列化數(shù)據(jù)的文件為參數(shù),調(diào)用一個(gè)binaryformatter實(shí)例的deserialize方法,就會(huì)返回一個(gè)對(duì)象,然后把它轉(zhuǎn)化為合適的類型。下面的代碼反序列化文件中的所有對(duì)象,然后處理所有的person對(duì)象:
 
   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()
下面的例子調(diào)用deserialize方法反序列化真?zhèn)€集合,然后把返回值轉(zhuǎn)換為合適的類型(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()

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 南投市| 财经| 大田县| 郑州市| 公主岭市| 旌德县| 哈巴河县| 丹江口市| 林甸县| 姜堰市| 安岳县| 丽水市| 天津市| 西华县| 长顺县| 轮台县| 五峰| 比如县| 武定县| 武宣县| 珠海市| 中方县| 霍林郭勒市| 宁远县| 绥化市| 屯留县| 六枝特区| 祁门县| 合作市| 松溪县| 贵州省| 尉氏县| 洪雅县| 崇礼县| 龙海市| 湖口县| 红河县| 蕲春县| 寿阳县| 彭阳县| 大方县|