Xamarin跨平台读写文件

Keywords:

概览

Xamarin.Forms代码在多个平台内运行–每个平台都有自己的文件系统.使用不同的平台原生的文件API读写文件是最简单的,除此之外,在一个App内,使用嵌入的资源是一个更简单的解决办法。本文档涵盖以下常见文件处理场景:

•作为资源嵌入的文件-文件可作为应用程序的一部分,使用Reflection API加载。

•保存和加载文件- 在本机-用户可写存储-内实现,使用DependencyService访问。


第三方组件调用PCLStorage也可用于从PCL代码读取和写入用户可访问存储的文件。

有关处理图像文件不同,请参阅下面的使用图像页面。

我的:http://www.songshizhao.com/blog/blogPage/161.html

官方:https://developer.xamarin.com/guides/xamarin-forms/user-interface/images/


加载嵌入的资源文件

把一个文件嵌入PCL 组件,首先创建或者附加一个文件,确保在属性中,生成操作选择[嵌入的资源]

GetManifestResourceStream用于使用其资源ID访问嵌入式文件。默认情况下,资源ID是其嵌入项目的默认命名空间的文件名,在这种情况下,程序集为WorkingWithFiles,文件名为PCLTextResource.txt,因此资源ID为WorkingWithFiles.PCLTextResource.txt。


varassembly=typeof(LoadResourceText).GetTypeInfo().Assembly;
Streamstream=assembly.GetManifestResourceStream("WorkingWithFiles.PCLTextResource.txt");
stringtext="";
using(varreader=newSystem.IO.StreamReader(stream)) {
    text=reader.ReadToEnd();
}


然后,文本变量可用于显示文本或以其他方式在代码中使用。示例应用程序的屏幕截图显示了Label控件中呈现的文本。Configuring embedded resource build action

加载和反序列化XML同样简单。以下代码显示了从资源加载和反序列化的XML文件,然后绑定到ListView进行显示。XML文件包含一个Monkey对象数组(该类在示例代码中定义)。


var assembly=typeof(LoadResourceText).GetTypeInfo().Assembly;
Streamstream=assembly.GetManifestResourceStream("WorkingWithFiles.PCLXmlResource.xml");
List<Monkey>monkeys;
using(varreader=newSystem.IO.StreamReader(stream)) {
   varserializer=newXmlSerializer(typeof(List<Monkey>));
    monkeys=(List<Monkey>)serializer.Deserialize(reader);
}
varlistView=newListView();
listView.ItemsSource=monkeys;


Text file embedded in PCL


同步项目-

说明第二个选项的代码如下所示。编译器指令用于选择硬编码资源前缀(通常与引用项目的默认命名空间相同)。resourcePrefix变量然后用于通过将其与嵌入的资源文件名相连接来创建有效的资源ID。

嵌入共享项目

  共享项目也可以将文件包含为嵌入式资源,但是由于共享项目的内容被编译到引用项目中,所以用于嵌入式文件资源ID的前缀将会更改。这意味着每个平台的每个嵌入式文件的资源ID可能不同。

共享项目有两个解决此问题的解决方案:


(1)同步项目 -编辑每个平台的项目属性以使用相同的程序集名称和默认命名空间。然后,该值可以作为“共享项目”中嵌入资源ID的前缀“硬编码”。

(2)#if编译器指令-使用编译器指令设置正确的资源ID前缀,并使用该值动态构建正确的资源ID。

  第二个选项的代码如下所示。编译器指令用于选择硬编码资源前缀(通常与引用项目的默认命名空间相同)。资源前缀变量然后用于通过将其与嵌入的资源文件名相连接来创建有效的资源ID。



#if__IOS__
varresourcePrefix="WorkingWithFiles.iOS.";
#endif
#if__ANDROID__
varresourcePrefix="WorkingWithFiles.Droid.";
#endif
#ifWINDOWS_PHONE
varresourcePrefix="WorkingWithFiles.WinPhone.";
#endif

Debug.WriteLine("Using this resource prefix: "+resourcePrefix);
// note that the prefix includes the trailing period '.' that is required
varassembly=typeof(SharedPage).GetTypeInfo().Assembly;
Streamstream=assembly.GetManifestResourceStream
    (resourcePrefix+"SharedTextResource.txt");


组织资源

上述示例假定该文件嵌入在PCL项目的根目录中,在这种情况下,资源ID的格式为Namespace.Filename.Extension,如WorkingWithFiles.PCLTextResource.txt和WorkingWithFiles.iOS.SharedTextResource.txt。

嵌入式资源可以组织在文件夹中。当嵌入资源放置在文件夹中时,文件夹名称将成为资源ID的一部分(以.分隔),因此资源ID格式将成为Namespace.Folder.Filename.Extension。将示例应用程序中使用的文件放入文件夹MyFolder将使相应的资源ID为WorkingWithFiles.MyFolder.PCLTextResource.txt和WorkingWithFiles.iOS.MyFolder.SharedTextResource.txt。


调试嵌入式资源

因为有时难以理解为什么没有加载特定资源,所以可以将以下调试代码临时添加到应用程序中,以帮助确认资源配置正确。它将把给定程序集中嵌入的所有已知资源输出到错误输出板,以帮助调试资源加载问题。


usingSystem.Reflection;
// ...
// use for debugging, not in released app code!
varassembly=typeof(SharedPage).GetTypeInfo().Assembly;
foreach(varresinassembly.GetManifestResourceNames()) {
   System.Diagnostics.Debug.WriteLine("found resource: "+res);
}


保存和加载文件

因为Xamarin.Forms在多个平台上运行,每个平台都有自己的文件系统。没有统一的方法可以加载和保存用户创建的文件。为了演示如何保存和加载文本文件,示例应用程序包括一个页面,用于保存和加载某些用户输入-完成的页面如下所示:

Saving and loading text

每个平台的目录结构略有不同,文件系统功能也不同-例如Xamarin.iOS和Xamarin.Android支持大多数System.IO功能,但Windows Phone仅支持IsolatedStorage和Windows.Storage API。

为了解决这个问题,示例应用程序在Xamarin.Forms PCL中定义了一个接口来加载和保存文件。它提供了一个简单的API来加载和保存将存储在设备上的文本文件。


publicinterfaceISaveAndLoad{
   voidSaveText(stringfilename,stringtext);
   stringLoadText(stringfilename);
}


PCL代码然后使用DependencyService来获取对接口本机实现的引用。这允许可移植代码将文件的加载和保存委托给在每个特定于平台的项目中编写的类。在示例中,保存和加载按钮如下所示:


varsaveButton=newButton{Text="Save"};
saveButton.Clicked+=(sender, e)=>{
   DependencyService.Get<ISaveAndLoad>().SaveText("temp.txt", input.Text);
};
varloadButton=newButton{Text="Load"};
loadButton.Clicked+=(sender, e)=>{
    output.Text=DependencyService.Get<ISaveAndLoad>().LoadText("temp.txt");
};


在实际保存和加载文件之前,需要在每个特定于平台的项目中添加一个实现。

iOS和Android平台

实现Xamarin.iOS和Xamarin.Android项目的接口可以相同。代码如下所示,其中包含DependencyService所需的[assembly:Dependency(typeof(SaveAndLoad))]属性。


 [assembly:Dependency(typeof(SaveAndLoad))]
namespaceWorkingWithFiles{
   publicclassSaveAndLoad:ISaveAndLoad{
       publicvoidSaveText(stringfilename,stringtext) {
           vardocumentsPath=Environment.GetFolderPath(Environment.SpecialFolder.Personal);
           varfilePath=Path.Combine(documentsPath, filename);
           System.IO.File.WriteAllText(filePath, text);
        }
       publicstringLoadText(stringfilename) {
           vardocumentsPath=Environment.GetFolderPath(Environment.SpecialFolder.Personal);
           varfilePath=Path.Combine(documentsPath, filename);
           returnSystem.IO.File.ReadAllText(filePath);
        }
    }
}


Universal Windows Platform (UWP)平台,Windows 8.1 and Windows Phone 8.1

这些平台有一个不同的文件API – Windows.Storage –(微软就是爱作死)用于保存和加载文件。ISaveAndLoad接口实现方式如下所示:


usingSystem;
usingSystem.Threading.Tasks;
usingWindows.Storage;
usingWinApp;
usingWorkingWithFiles;
usingXamarin.Forms;

[assembly:Dependency(typeof(SaveAndLoad_WinApp))]

namespaceWindowsApp
{
   //https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh758325.aspx
   publicclassSaveAndLoad_WinApp:ISaveAndLoad
    {
       publicasyncTaskSaveTextAsync(stringfilename,stringtext)
        {
           StorageFolderlocalFolder=ApplicationData.Current.LocalFolder;
           StorageFilesampleFile=await localFolder.CreateFileAsync(filename,CreationCollisionOption.ReplaceExisting);
            awaitFileIO.WriteTextAsync(sampleFile, text);
        }
       publicasyncTask<string>LoadTextAsync(stringfilename)
        {
           StorageFolderstorageFolder=ApplicationData.Current.LocalFolder;
           StorageFilesampleFile=await storageFolder.GetFileAsync(filename);
           stringtext=awaitWindows.Storage.FileIO.ReadTextAsync(sampleFile);
           returntext;
        }
    }
}


在共享项目中保存和加载文件

因为共享项目支持编译指令,可以将共享项目中的所有平台特定代码包含在单个类文件中(不使用DependencyService)。可以只编写一个包含上述两个实现的SaveAndLoad类,使用#if WINDOWS_PHONE,#if __IOS__和#if __ANDROID__等编译器指令选择性地编译到引用项目中。

更多信息

基于PCL的Xamarin.Forms项目可以利用 PCLStorage NuGet (code & documentation)帮助跨平台实现文件操作。

总结

本文档显示了一些简单的文件操作,用于加载嵌入式资源,并在设备上保存和加载文本。开发人员可以使用DependencyService实现自己的本地文件API,使其根据需要复杂,以处理其文件操作需求。我简单翻译了一下。

本文word下载链接: https://pan.baidu.com/s/1eSvdI3g 密码: 2w6h

作者:songshizhao 发表于:2017-05-14T10:01:15 访问量:1443