【Win 10 应用开发】文件读写的三种方案
本文老周就跟伙伴們探討一下關(guān)于文件讀寫(xiě)的方法??偟脕?lái)說(shuō)嘛,有三種方案可以用,而且每種方案都各有特色,也說(shuō)不上哪種較好。反正你得記住老祖宗留給我們的大智慧——事無(wú)定法,靈活運(yùn)用者為上。
OK,咱們開(kāi)始吧。
?
先說(shuō)第一個(gè)方案:使用 FileIO類。
這個(gè)類屬于RT庫(kù)API,它公開(kāi)了一堆靜態(tài)方法,可以直接調(diào)用,快捷方便,就像.net里面的File類一樣。在使用FileIo類的時(shí)候,需要一個(gè)引用已知文件的StorageFile實(shí)例,而且FileIo只能操作已經(jīng)存在的文件,它不會(huì)自動(dòng)創(chuàng)建文件,這一點(diǎn)要注意。
下面代碼演示如何用FileIO類把文本內(nèi)容寫(xiě)入文件中。
// 獲取文檔庫(kù)StorageFolder doclib = KnownFolders.DocumentsLibrary;// 創(chuàng)建新文件StorageFile newfile = await doclib.CreateFileAsync("test.txt", CreationCollisionOption.OpenIfExists);// 將文本寫(xiě)入文件await FileIO.WriteTextAsync(newfile, content, UnicodeEncoding.Utf8);在讀寫(xiě)文本的時(shí)候,強(qiáng)烈建議明確指定為UTF-8編碼,這樣做可以減少靈異事件發(fā)生的概率,信不信由你。
在調(diào)用CreateFileAsync方法創(chuàng)建新文件時(shí),可以同時(shí)只定一個(gè)CreationCollisionOption枚舉的值,如果值為FailIfExists,表示當(dāng)文件已經(jīng)存在時(shí)會(huì)引發(fā)異常;我這里選用OpenIfExists,即如果文件不存在就創(chuàng)建,如果存在就打開(kāi)現(xiàn)有文件;如果值為ReplaceExisting,就替換現(xiàn)有文件。
?
下面代碼讀從剛才保存的文件中將文本讀出來(lái)。
try{// 訪問(wèn)文檔庫(kù)StorageFolder doclib = KnownFolders.DocumentsLibrary;// 獲取剛才保存的文件StorageFile file = await doclib.GetFileAsync(filename);if (file != null){// 讀入內(nèi)容displayContent = await FileIO.ReadTextAsync(file, UnicodeEncoding.Utf8);}}catch (FileNotFoundException){displayContent = "文件不存在。";}catch (Exception ex){displayContent = ex.Message;}如果要打開(kāi)的文件不存在,會(huì)引發(fā)FileNotFoundException異常,所以我特特地捕捉這個(gè)異常,為的是在文件不存在時(shí)向用戶反饋。
這里有個(gè)關(guān)鍵點(diǎn),大家要記清,你寫(xiě)入文本時(shí)用的是Utf-8編碼,在讀出來(lái)的時(shí)候也要使用匹配的編碼格式,在民政局登記領(lǐng)證時(shí),你總不能寫(xiě)別人家老婆的名字吧。
?
第二種方案用的也是RT庫(kù)的API,即DataWriter和DataReader類。這與FileIO還是有不同的,FileIO所針對(duì)的文件對(duì)象,而DataReader和DataWriter所針對(duì)的是流,文件流、內(nèi)存流、網(wǎng)絡(luò)流都可以用,它們所面向的應(yīng)用范圍不同,當(dāng)然,是可以用來(lái)讀寫(xiě)文件流的。
下面代碼演示將當(dāng)前時(shí)間寫(xiě)入文件。
// 獲取文檔庫(kù)StorageFolder doclib = KnownFolders.DocumentsLibrary;// 創(chuàng)建文件StorageFile file = await doclib.CreateFileAsync("new.txt", CreationCollisionOption.ReplaceExisting);// 打開(kāi)文件流using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite)){DataWriter dw = new DataWriter(stream);// 寫(xiě)入時(shí)間 dw.WriteDateTime(DateTimeOffset.Now);// 提交數(shù)據(jù)到流await dw.StoreAsync();// 收工 dw.Dispose();}在調(diào)用StorageFile的OpenXXXAsync方法可以打開(kāi)用來(lái)讀寫(xiě)文件的流,要是想讓打開(kāi)的流支持寫(xiě)入行為,應(yīng)該調(diào)用OpenAsync方法,并在參數(shù)中傳遞FileAccessMode.ReadWrite值,說(shuō)明可讀可寫(xiě),如果是Read,那就只能讀不能寫(xiě)了。當(dāng)然了,如果是只讀的話,也可以直接調(diào)用OpenReadAsync方法。
DataWriter類公開(kāi)了N個(gè)WriteXXXXX方法,可以寫(xiě)入許多基礎(chǔ)類型,比如字節(jié)、int、double、字符串等,當(dāng)然也包括日期時(shí)間。
大家要記住,在你寫(xiě)完數(shù)據(jù)后,記得調(diào)用StoreAsync方法,因?yàn)閣riter在寫(xiě)入時(shí)不會(huì)馬上就寫(xiě)入流中,它是先把數(shù)據(jù)寫(xiě)入到緩沖區(qū)中,等到StoreAsync方法調(diào)用后,就會(huì)把緩沖區(qū)中的內(nèi)容寫(xiě)入流,然后清理緩沖區(qū)。
在DataWriter的緩沖區(qū)中存在沒(méi)有保存到流的數(shù)據(jù)時(shí),UnstoredBufferLength屬性可返回未保存的數(shù)據(jù)大小,如果調(diào)用StoreAsync后,這個(gè)屬性會(huì)變?yōu)?。
?
下面代碼演示讀出剛剛保存到文件中的時(shí)間。
// 獲取文件StorageFile file = await doclib.GetFileAsync(filename);if (file != null){// 打開(kāi)流using(IRandomAccessStream stream = await file.OpenReadAsync()){// 讀出時(shí)間using (DataReader dr=new DataReader(stream)){await dr.LoadAsync((uint)stream.Size);DateTimeOffset dt = dr.ReadDateTime();displaystr = dt.ToString("yyyy年M月d日 HH:mm:ss");}}}}catch (FileNotFoundException){displaystr = "未找到文件。";}catch (Exception ex){displaystr = ex.Message;}實(shí)例化DataReader后,不要急著讀,因?yàn)閿?shù)據(jù)還在流中,不在reader的緩沖區(qū)中,所以,你應(yīng)當(dāng)先調(diào)用LoadAsync方法來(lái)加載內(nèi)容,參數(shù)是要加載的字節(jié)數(shù),返回值是實(shí)際加載的大小。加載好之后,你就可以讀了。
?
第三種方案是混合.NET和RT庫(kù)的API來(lái)讀寫(xiě)。在System.IO命名空間下,定義了兩個(gè)擴(kuò)展類。
第一個(gè)是WindowsRuntimeStorageExtensions,它是針對(duì)StorageFile類的擴(kuò)展,比如,調(diào)用OpenStreamForWriteAsync方法就可以直接得到一個(gè).net中的Stream實(shí)例,這樣你就可以用慣用的.net方式來(lái)讀寫(xiě)了。
另一個(gè)是WindowsRuntimeStreamExtensions,它是針對(duì)流的擴(kuò)展,支持將.net中的流與RT中的流進(jìn)行相互轉(zhuǎn)換。
有人會(huì)問(wèn)了,既然有RT的API了,為什么還要讓它與.net交互呢。你想想就知道了。
1、UWP支持的編寫(xiě)語(yǔ)言中有JS、C++,也有VB.NET和C#,C#和VB都是基于.net的語(yǔ)言,所以在UWP應(yīng)用代碼中你才能使用C#的基本類型,如int,byte,double,bool,string,float等,就是因?yàn)樗莾蓚€(gè)API子集的合體,沒(méi)有.net core就無(wú)法用這些語(yǔ)言寫(xiě)代碼了。
2、如果一些第三方類庫(kù)使用的是.net core開(kāi)發(fā)的可以跨平臺(tái)移植的呢,那也得需要這種交互才能相互調(diào)用。
?
其實(shí)這沒(méi)什么難理解的,就像中西藥可以結(jié)合一起用一樣的道理,把腦子放靈活一點(diǎn)就沒(méi)什么不能理解的了。
?
下面代碼演示寫(xiě)入文件。
StorageFile file = await doclib.CreateFileAsync("some.txt", CreationCollisionOption.ReplaceExisting);Tag = file.Name;using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite)){// 轉(zhuǎn)化為.net IO 流using (StreamWriter writer = new StreamWriter(stream.AsStreamForWrite(), System.Text.Encoding.UTF8)){// 寫(xiě)入內(nèi)容 writer.Write(content);}}?
下面代碼演示讀出內(nèi)容。
try{StorageFile file = await doc.GetFileAsync(filename);using (IRandomAccessStream stream = await file.OpenReadAsync()){using (StreamReader rd = new StreamReader(stream.AsStreamForRead(), System.Text.Encoding.UTF8)){tb.Text = rd.ReadToEnd();}}}catch (FileNotFoundException){tb.Text = "未找到文件。";}catch (Exception ex){tb.Text = ex.Message;}?
StreamWriter和StreamReader我就不介紹了,在.net里面玩得多了。
?
?
行了,三種方案都介紹完了,至于怎么用,自己看著辦吧,還是那句話——事無(wú)定法。
?
示例源代碼下載
?
========================================================
下面時(shí)間,講個(gè)小故事。
你要是問(wèn)我:老周,你的記憶力是不是特別好。
還真是,但那是小時(shí)候,不知道為什么,越長(zhǎng)大好像記憶力越后退。想想老周上小學(xué)的時(shí)候,從來(lái)不復(fù)習(xí)都可以考全級(jí)第一名,當(dāng)然,全級(jí)總?cè)藬?shù)也就90來(lái)人,呵呵。
就連語(yǔ)文課本上要背的課文、古詩(shī),英語(yǔ)課本上的對(duì)話,老周都不用課后去背,直接在課堂上完成,回家后壓根不用復(fù)習(xí)。也不知道什么原因,那個(gè)時(shí)候真的可以說(shuō)是過(guò)目不忘。
上了初中后就不太行了,看一遍根本記不下來(lái),少說(shuō)也要看兩到三遍,尤其是背文言文。反正總感覺(jué)年齡大了,記憶力衰退。小時(shí)候可以過(guò)目不忘的本領(lǐng)全沒(méi)了,現(xiàn)在拿一首唐詩(shī)出來(lái),我起碼也得讀上N遍,抄上M回才能背下來(lái),根本失去了小時(shí)候那種可以看一遍就背下來(lái)的能力了。
唉,想來(lái)歲月真是一把手術(shù)刀,把記憶力都一刀一刀地削去了。
?
總結(jié)
以上是生活随笔為你收集整理的【Win 10 应用开发】文件读写的三种方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: 微软发布紧急更新:修复Flash高危漏洞
- 下一篇: kettle中使用javascript步
