【Win 10 应用开发】文件读写的三种方案

Cle****-he UID.1073626
2016-03-22 发表

关于文件读写的方法,总得来说有三种方案可以用,而且每种方案都各有特色,也说不上哪种较好。反正你得记住老祖宗留给我们的大智慧——事无定法,灵活运用者为上。

OK,开始吧。



先说第一个方案:使用 FileIO类。

这个类属于RT库API,它公开了一堆静态方法,可以直接调用,快捷方便,就像.net里面的File类一样。在使用FileIo类的时候,需要一个引用已知文件的StorageFile实例,而且FileIo只能操作已经存在的文件,它不会自动创建文件,这一点要注意。

下面代码演示如何用FileIO类把文本内容写入文件中。
[mw_shl_code=csharp,true]// 获取文档库
StorageFolder doclib = KnownFolders.DocumentsLibrary;
// 创建新文件
StorageFile newfile = await doclib.CreateFileAsync("test.txt", CreationCollisionOption.OpenIfExists);

// 将文本写入文件
await FileIO.WriteTextAsync(newfile, content, UnicodeEncoding.Utf8);[/mw_shl_code]


在读写文本的时候,强烈建议明确指定为UTF-8编码,这样做可以减少灵异事件发生的概率,信不信由你。
在调用CreateFileAsync方法创建新文件时,可以同时只定一个CreationCollisionOption枚举的值,如果值为FailIfExists,表示当文件已经存在时会引发异常;我这里选用OpenIfExists,即如果文件不存在就创建,如果存在就打开现有文件;如果值为ReplaceExisting,就替换现有文件。



下面代码从刚才保存的文件中将文本读出来。
[mw_shl_code=csharp,true] try
{
// 访问文档库
StorageFolder doclib = KnownFolders.DocumentsLibrary;
// 获取刚才保存的文件
StorageFile file = await doclib.GetFileAsync(filename);

if (file != null)
{
// 读入内容
displayContent = await FileIO.ReadTextAsync(file, UnicodeEncoding.Utf8);
}
}
catch (FileNotFoundException)
{
displayContent = "文件不存在。";
}
catch (Exception ex)
{
displayContent = ex.Message;
}[/mw_shl_code]


如果要打开的文件不存在,会引发FileNotFoundException异常,所以我特特地捕捉这个异常,为的是在文件不存在时向用户反馈。
这里有个关键点,大家要记清,你写入文本时用的是Utf-8编码,在读出来的时候也要使用匹配的编码格式,在民政局登记领证时,你总不能写别人家老婆的名字吧。



第二种方案用的也是RT库的API,即DataWriter和DataReader类。这与FileIO还是有不同的,FileIO所针对的文件对象,而DataReader和DataWriter所针对的是流,文件流、内存流、网络流都可以用,它们所面向的应用范围不同,当然,是可以用来读写文件流的。

下面代码演示将当前时间写入文件。
[mw_shl_code=csharp,true]// 获取文档库
StorageFolder doclib = KnownFolders.DocumentsLibrary;
// 创建文件
StorageFile file = await doclib.CreateFileAsync("new.txt", CreationCollisionOption.ReplaceExisting);

// 打开文件流
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
DataWriter dw = new DataWriter(stream);
// 写入时间
dw.WriteDateTime(DateTimeOffset.Now);
// 提交数据到流
await dw.StoreAsync();
// 收工
dw.Dispose();
}[/mw_shl_code]


在调用StorageFile的OpenXXXAsync方法可以打开用来读写文件的流,要是想让打开的流支持写入行为,应该调用OpenAsync方法,并在参数中传递FileAccessMode.ReadWrite值,说明可读可写,如果是Read,那就只能读不能写了。当然了,如果是只读的话,也可以直接调用OpenReadAsync方法。

DataWriter类公开了N个WriteXXXXX方法,可以写入许多基础类型,比如字节、int、double、字符串等,当然也包括日期时间。

大家要记住,在你写完数据后,记得调用StoreAsync方法,因为writer在写入时不会马上就写入流中,它是先把数据写入到缓冲区中,等到StoreAsync方法调用后,就会把缓冲区中的内容写入流,然后清理缓冲区。

在DataWriter的缓冲区中存在没有保存到流的数据时,UnstoredBufferLength属性可返回未保存的数据大小,如果调用StoreAsync后,这个属性会变为0。



下面代码演示读出刚刚保存到文件中的时间。
[mw_shl_code=csharp,true] // 获取文件
StorageFile file = await doclib.GetFileAsync(filename);
if (file != null)
{
// 打开流
using(IRandomAccessStream stream = await file.OpenReadAsync())
{
// 读出时间
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;
}[/mw_shl_code]


实例化DataReader后,不要急着读,因为数据还在流中,不在reader的缓冲区中,所以,你应当先调用LoadAsync方法来加载内容,参数是要加载的字节数,返回值是实际加载的大小。加载好之后,你就可以读了。



第三种方案是混合.NET和RT库的API来读写。在System.IO命名空间下,定义了两个扩展类。

第一个是WindowsRuntimeStorageExtensions,它是针对StorageFile类的扩展,比如,调用OpenStreamForWriteAsync方法就可以直接得到一个.net中的Stream实例,这样你就可以用惯用的.net方式来读写了。

另一个是WindowsRuntimeStreamExtensions,它是针对流的扩展,支持将.net中的流与RT中的流进行相互转换。

有人会问了,既然有RT的API了,为什么还要让它与.net交互呢。你想想就知道了。

1、UWP支持的编写语言中有JS、C++,也有VB.NET和C#,C#和VB都是基于.net的语言,所以在UWP应用代码中你才能使用C#的基本类型,如int,byte,double,bool,string,float等,就是因为它是两个API子集的合体,没有.net core就无法用这些语言写代码了。

2、如果一些第三方类库使用的是.net core开发的可以跨平台移植的呢,那也得需要这种交互才能相互调用。



其实这没什么难理解的,就像中西药可以结合一起用一样的道理,把脑子放灵活一点就没什么不能理解的了。



下面代码演示写入文件。
[mw_shl_code=csharp,true]StorageFile file = await doclib.CreateFileAsync("some.txt", CreationCollisionOption.ReplaceExisting);
Tag = file.Name;
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
// 转化为.net IO 流
using (StreamWriter writer = new StreamWriter(stream.AsStreamForWrite(), System.Text.Encoding.UTF8))
{
// 写入内容
writer.Write(content);
}
}[/mw_shl_code]


下面代码演示读出内容。
[mw_shl_code=csharp,true] 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;
}[/mw_shl_code]


StreamWriter和StreamReader我就不介绍了,在.net里面玩得多了。


行了,三种方案都介绍完了,至于怎么用,自己看着办吧,还是那句话——事无定法。


源代码下载:***链接停止解析***


来自:老周博客 开发者交流群:53078485,期待你的加入!

敬告:
为防止不可控的内容风险,本站已关闭新用户注册,新贴的发表及评论;
你现在看到的内容只是互联网用户曾经发表的言论快照,仅用于老用户留存纪念,且仅与科技行业相关,全部内容不代表本站观点及立场;
本站重新开放前已针对包括用户隐私、版权保护、信息安全、国家政策在内的各种互联网法律法规要求,执行了隐患内容的自查、屏蔽和删除;
本站目前所属个人主体,未有任何盈利安排与计划,且与原WFUN.COM所属公司不存在任何关联关系;
如果本帖内容或者相关资源侵犯到您的合法权益,或者您认为存在问题,那么请您务必点此举报或投诉!
全部回复:
leonmaru UID.1223618
2016-03-22 回复

对,多点这种帖子比较好。

其实我也挺想开发UWP的,一直手痒痒,只不过现在工作比较忙。

以后闲了,一定写一个练练手!

clwp70316 UID.243902
2016-03-22 回复

使用Buffer读写
还有使用IRandomAccessStream 的stream读写 也可以讲一讲

本站使用Golang构建,点击此处申请开源鄂ICP备18029942号-4联系站长投诉/举报