Windows Phone上的许多应用的应用场景不仅仅依赖从第三方服务或者APIs接收过来的数据,还依赖于那些暂时或者永久性的存储在独立设备上的数据。Windows Phone 7提供开发者利用独立储存的能力。独立存储是直接绑定一个既有应用的、沙箱化的存储配置方案。Windows Phone 8扩展了这部分存储的大小,同时还提供了一些附加的选项。
在这篇文章里我将介绍 Windows.Storage 命名空间,WinPRT API,Microsoft.Phone.Storage和.NET提供的标准API。

设备存储

首先我们看看ApplicationData。这个类允许你访问本地应用程序数据缓存。从某种程度上说,这很像 Isolated Storage- 它仍然是与应用程序相关联的。和其他应用的数据内容一样,在卸载应用程序时数据也同时删除。所以,如果用户希望在应用删除后还能查看到原来的数据,那么就需要考虑其他的存储方式了,比如 SkyDrive。
在手机上应用程序的数据存放的文件夹地址类似如下:
C:\Data\Users\DefApps\AppData\{5D93133B-3B39-4ABF-8D61-277D77B9F2AD}\Local
GUID 是应用程序的唯一标识,它定义在WMAppManifest.xml文件中。如果你以前开发过Windows Store应用程序,你可能对ApplicationDataContainer这个更加熟悉。不过,有一些特殊的限制你需要注意一下,举个例子,比如像 ApplicationData.Current.LocalSettings和ApplicationData.Current.RoamingFolder这样的好东西在Windows Phone并没有实现。
现在来看看关于文件夹的一般操作, 接下来我们就要开始储存数据了. 其实方法和Windows Store应用程序中的非常相似:
async void WriteData(string fileName, string content)
{
byte[] data = Encoding.UTF8.GetBytes(content);
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (Stream s = await file.OpenStreamForWriteAsync())
{
await s.WriteAsync(data, 0, data.Length);
}
}

上面的代码片段表示了在本地应用程序数据文件夹中的一个任意文件中储存一个字符串. 在这里你需要格外注意的核心类是StorageFolder StorageFile. StorageFolder允许你访问根目录容器及执行指定操作, 如获取文件或新建文件, StorageFile实际上就是允许你访问文件容器. 上面的示例中, 在使用一个数据参数来调用WriteAsync后,文件就已经打开,可以写入了. 这个参数也不一定要是字符串的字节数组,它可以是图片,音乐文件或者视频文件 – 你想存什么就存什么.
当你创建一个新文件,如果出现文件名冲突的情况(当前文件夹下存在同名文件),你可以通过CreationCollisionOption来选择如何进行处理。大多数情况下,程序会直接覆盖现有文件。对于这种情况,我有个建议,如果这块文件存储区域不是供程序内部使用,而且是对用户开放的,那么告知你的用户,当文件创建完后,一些数据可能会丢失。
读取文件的代码可以很容易地写在一个异步函数中,就像下面这样:
async Task ReadData(string fileName)
{
byte[] data;
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.GetFileAsync(fileName);
using (Stream s = await file.OpenStreamForReadAsync())
{
data = new byte[s.Length];
await s.ReadAsync(data, 0, (int)s.Length);
}
return Encoding.UTF8.GetString(data, 0, data.Length);
}

值得再次注意的是,我通过StorageFolder 和 StorageFile 访问文件中的内容,我这次打开的是基本的输入流而不是输出流(也就是说,这次是读文件而不是写文件)。应用程序的数据只能存储在设备内部而不是外部存储设备上。

外部存储

但是,正如你所知道的,Windows Phone 8现在支持额外的存储器,例如SD卡。 这是这些类通过Microsoft.Phone.Storage展示它们派得上用场的地方。通过以下方式能够轻易的得到当前可用的外部存储设备列表:
var storageAssets = await ExternalStorage.GetExternalStorageDevicesAsync();

假如只有一个外部存储卡,你可以通过 LINQ 来获取展示实例:
ExternalStorageDevice item = storageAssets.FirstOrDefault();
不过也有限制,第三方应用访问外部存储是只读模式。
注意:尽管你可以从外部存储设备上获取当前实例,而且不会报任何错,但是当你尝试获取文件夹和文件列表时,你会碰到一个程序异常,除非你的程序中启用了ID_CAP_REMOVABLE_STORAGE。
你可以通过下面这种简单的方式获取目录下的文件夹列表:
var storageAssets = await ExternalStorage.GetExternalStorageDevicesAsync();
ExternalStorageDevice item = storageAssets.FirstOrDefault();
ExternalStorageFolder folder = item.RootFolder;
var _folderList = await folder.GetFoldersAsync();
foreach (var _folder in _folderList)
{
Debug.WriteLine(_folder.Name);
}

即使你能轻易地获取文件夹列表,但是你也无法取得文件夹下的文件,除非你明确得将应用程序和文件的文件类型关联在一起。要做到这一点,你必须打开WMAppManifest.xml文件,并添加一个Extensions节点,在节点中添加相关的文件类型信息:



Assets/Tiles/FlipCycleTileSmall.png
Assets/Tiles/FlipCycleTileMedium.png
Assets/Tiles/FlipCycleTileLarge.png


.psd



然后,你就可以获取文件下的文件了,其他文件夹下的文件也可以通过相同的方法获得:
var storageAssets = await ExternalStorage.GetExternalStorageDevicesAsync();
ExternalStorageDevice item = storageAssets.FirstOrDefault();
ExternalStorageFolder folder = item.RootFolder;
var imagesFolder = await folder.GetFolderAsync("images");
var fileList = await imagesFolder.GetFilesAsync();

记住:你只能获得那些扩展名位于WMAppManifest.xml文件的Extensions 节点中的ExternalStorageFile 实例。
原文:DZONE