存储和检索设置以及其他应用数据

应用数据是由特定应用创建和管理的可变数据。 它包含运行时状态、应用设置、用户首选项、参考内容(如字典应用中的字典定义)以及其他设置。 应用数据不同于“用户数据”,即用户在使用应用时创建和管理的数据。 用户数据包括文档或媒体文件、电子邮件或通信记录,或保存用户创建的内容的数据库记录。 用户数据可能对多个应用有用或有意义。 通常,这是用户希望作为独立于应用本身的实体进行操作或传输的数据(例如文档)。

有关应用数据的重要说明:应用数据的生存期与应用的生存期相关联。 如果删除应用,所有应用数据都会因此丢失。 不可使用应用数据来存储用户数据或用户可能认为是有价值的和不可替代的任何内容。 建议使用用户的资料库和 Microsoft OneDrive 来存储此类信息。 应用数据非常适合用于存储特定于应用的用户偏好设置、设置和收藏夹。

应用数据的类型

有两种类型的应用数据:设置和文件。

设置

使用设置来存储用户偏好设置和应用程序状态信息。 应用数据 API 使你能够轻松创建和取回设置(本文稍后将向你展示一些示例)。

下面是可用于应用设置的数据类型:

  • UInt8Int16UInt16Int32UInt32Int64UInt64SingleDouble
  • 布尔值
  • Char16String
  • DateTimeTimeSpan
  • GUIDPointSizeRect
  • ApplicationDataCompositeValue:一组必须按原子方式序列化和反序列化的相关应用设置。 使用复合设置可轻松处理相互依赖的设置的原子更新。 系统会确保在并发访问和漫游期间复合设置的完整性。 复合设置针对少量数据进行了优化,如果将其用于大型数据集,性能可能会变差。

文件

使用文件来存储二进制数据或启用自己的自定义序列化类型。

在应用数据存储中存储应用数据

安装应用后,系统会为设置和文件提供自己的按用户数据存储。 无需知道此数据存在的位置或方式,因为系统负责管理物理存储,确保数据与其他应用和其他用户保持隔离。 当用户安装对应用的更新时,系统也会保留这些数据存储的内容;在卸载应用时,则会完全干净地删除这些数据存储的内容。

在其应用数据存储中,每个应用都有系统定义的根目录:一个用于本地文件,一个用于漫游文件,还有一个用于临时文件。 你的应用程序可以向这些根目录中添加新文件和新容器。

本地应用数据

本地应用数据应当用于需要在应用会话之间保留,并且不适合漫游应用数据的任何信息。 在其他设备上不适用的数据也应在此处存储。 对存储的本地数据没有一般性的大小限制。 将本地应用数据存储用于不具漫游意义的数据和大型数据集。

取回本地应用数据存储

在读取或写入本地应用数据之前,必须取回本地应用数据存储。 若要取回本地应用数据存储,可使用 ApplicationData.LocalSettings 属性获取应用的本地设置作为 ApplicationDataContainer 对象。 使用 ApplicationData.LocalFolder 属性获取 StorageFolder 对象中的文件。 使用 ApplicationData.LocalCacheFolder 属性获取本地应用数据存储中的文件夹,你可以在其中保存备份和还原中不包含的文件。

Windows.Storage.ApplicationDataContainer localSettings = 
    Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder = 
    Windows.Storage.ApplicationData.Current.LocalFolder;

创建和取回简单的本地设置

若要创建或写入设置,请使用 ApplicationDataContainer.Values 属性访问我们在上一步中获取的 localSettings 容器中的设置。 此示例创建一个名为 exampleSetting 的设置。

// Simple setting

localSettings.Values["exampleSetting"] = "Hello Windows";

若要取回设置,请使用用于创建设置的相同 ApplicationDataContainer.Values 属性。 此示例演示如何取回刚刚创建的设置。

// Simple setting
Object value = localSettings.Values["exampleSetting"];

创建和取回本地复合值

若要创建或写入复合值,可创建 ApplicationDataCompositeValue 对象。 此示例创建一个名为 exampleCompositeSetting 的复合设置,并将其添加到 localSettings 容器。

// Composite setting

Windows.Storage.ApplicationDataCompositeValue composite = 
    new Windows.Storage.ApplicationDataCompositeValue();
composite["intVal"] = 1;
composite["strVal"] = "string";

localSettings.Values["exampleCompositeSetting"] = composite;

此示例演示如何取回刚刚创建的复合值。

// Composite setting

Windows.Storage.ApplicationDataCompositeValue composite = 
   (Windows.Storage.ApplicationDataCompositeValue)localSettings.Values["exampleCompositeSetting"];

if (composite == null)
{
   // No data
}
else
{
   // Access data in composite["intVal"] and composite["strVal"]
}

创建和读取本地文件

若要在本地应用数据存储中创建和更新文件,请使用文件 API,例如 Windows.Storage.StorageFolder.CreateFileAsyncWindows.Storage.FileIO.WriteTextAsync。 此示例在 localFolder 容器中创建一个名为 dataFile.txt 的文件,并将当前日期和时间写入文件。 CreationCollisionOption 枚举中的 ReplaceExisting 值指示替换文件(如果其已存在)。

async void WriteTimestamp()
{
   Windows.Globalization.DateTimeFormatting.DateTimeFormatter formatter = 
       new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("longtime");

   StorageFile sampleFile = await localFolder.CreateFileAsync("dataFile.txt", 
       CreationCollisionOption.ReplaceExisting);
   await FileIO.WriteTextAsync(sampleFile, formatter.Format(DateTimeOffset.Now));
}

若要在本地应用数据存储中打开和读取文件,请使用文件 API,例如 Windows.Storage.StorageFolder.GetFileAsyncWindows.Storage.StorageFile.GetFileFromApplicationUriAsyncWindows.Storage.FileIO.ReadTextAsync。 本示例打开在上一步中创建的 dataFile.txt 文件,并从文件读取日期。 有关从各种位置加载文件资源的详细信息,请参阅如何加载文件资源

async void ReadTimestamp()
{
   try
   {
      StorageFile sampleFile = await localFolder.GetFileAsync("dataFile.txt");
      String timestamp = await FileIO.ReadTextAsync(sampleFile);
      // Data is contained in timestamp
   }
   catch (Exception)
   {
      // Timestamp not found
   }
}

漫游数据

警告

自 Windows 11 起,不再支持漫游数据和设置。 建议的替代产品为 Azure 应用服务。 Azure 应用服务广受支持、记录良好、可靠,并且支持跨平台/跨生态系统场景,例如 iOS、Android 和 Web。

以下文档适用于 Windows 10 版本 1909 及更低版本。

如果在应用中使用漫游数据,则用户可以轻松地在多个设备之间保持应用的应用数据同步。 如果用户在多个设备上安装应用,OS 会将应用数据保持同步,从而减少用户在其第二台设备上所需为应用执行的设置工作量。 漫游还使用户能够继续执行任务,例如撰写列表,甚至可以在其他设备上自离开的位置接续工作。 OS 在更新时将漫游数据复制到云中,并将数据同步到安装应用的其他设备。

OS 会限制每个应用可以漫游的应用数据的大小。 请参阅 ApplicationData.RoamingStorageQuota。 如果应用达到此限制,则应用的应用数据完全不会复制到云,直到应用的总漫游应用数据再次小于限制。 因此,最佳做法是仅对用户偏好设置、链接和小型数据文件使用漫游数据。

只要用户在所需时间间隔内从某个设备访问应用,即可在云中获取应用的漫游数据。 如果用户超过此时间间隔不运行应用,则会从云中删除其漫游数据。 如果用户卸载应用,不会从云中自动删除其漫游数据,而是会保留此等数据。 如果用户在时间间隔内重新安装应用,则漫游数据将从云端同步。

漫游数据相关的适当和不当操作

请参阅关于漫游数据的重要说明。

  • 为用户首选项和自定义信息、链接以及小型数据文件使用漫游。 例如,使用漫游在所有设备上保留用户的背景色偏好设置。
  • 使用漫游使用户可以跨设备继续执行任务。 例如,漫游应用数据,包括草稿电子邮件的内容或阅读器应用中最近查看的页面。
  • 通过更新应用数据来处理 DataChanged 事件。 当应用数据刚刚从云端完成同步时,会发生此事件。
  • 漫游对内容的引用,而不是漫游原始数据。 例如,对 URL 进行漫游,而不是漫游联机文章的内容。
  • 对于重要的时间关键型设置,请使用与 RoamingSettings 关联的 HighPriority 设置。
  • 不要漫游特定于设备的应用数据。 某些信息仅在本地是相关的,例如本地文件资源的路径名称。 如果决定了要漫游本地信息,请确保一旦信息在辅助设备上无效,应用可以恢复。
  • 不可漫游大型应用数据集。 应用可漫游的应用数据量有限制;使用 RoamingStorageQuota 属性获取此最大值。 如果应用达到此限制,则在应用数据存储的大小不再超过此限制之前,任何数据都无法漫游。 设计应用时,请考虑如何对较大的数据施加约束,以免超出限制。 例如,如果每次保存游戏状态需要 10KB,应用可能只允许用户存储最多 10 个游戏。
  • 不要对依赖于即时同步的数据使用漫游。 Windows 不保证即时同步;如果用户处于脱机状态或处于高延迟网络上,则漫游可能会显著延迟。 确保 UI 不依赖于即时同步。
  • 请勿针对频繁更改的数据使用漫游。 例如,如果应用跟踪频繁更改的信息(例如歌曲中以秒衡量的位置),请不要将其存储为漫游应用数据。 相反,请选择仍然提供良好用户体验的不太频繁的表示形式,如当前正在播放的歌曲。

漫游先决条件

请参阅关于漫游数据的重要说明。

如果用户使用 Microsoft 帐户登录到其设备,则任何用户都可以从漫游应用数据中受益。 但是,用户和组策略管理员可以随时关闭设备上的漫游应用数据。 如果用户选择不使用 Microsoft 帐户或者禁用漫游数据功能,她仍可以使用你的应用,但应用数据都将留在每台设备本地。

只有用户将设备设置为“受信任”设备时,PasswordVault 中存储的数据才会传输。 如果设备不受信任,则此保管库中保存的数据不会漫游。

冲突解决

请参阅关于漫游数据的重要说明。

漫游应用数据不适合一次在多台设备上同时使用。 如果在同步期间发生冲突,因为两台设备上更改了特定数据单元,则系统将始终偏向最后写入的值。 这可确保应用利用最新的信息。 如果数据单元是设置复合单元,则设置单元级别仍会发生冲突解决,这意味着将同步具有最新更改的复合单元。

何时写入数据

请参阅关于漫游数据的重要说明。

根据设置的预期生存期,应在不同的时间写入数据。 不经常更改的或更改缓慢的应用数据应立即写入。 但是,经常更改的应用数据则只应当按固定间隔定期写入(例如每 5 分钟一次),以及在暂停应用时写入。 例如,开始播放新歌曲时,音乐应用就可立即写入“当前歌曲”设置,不过,歌曲中的实际位置则仅应在应用暂停时写入。

过度使用保护

请参阅关于漫游数据的重要说明。

该系统具有各种保护机制,以避免资源的不当使用。 如果应用数据未按预期转换,则可能是设备暂时受到限制。 等待一段时间通常会自动解决这种情况,无需执行任何操作。

版本控制

请参阅关于漫游数据的重要说明。

应用数据可以利用版本控制从一个数据结构升级到另一个。 版本号与应用版本不同,可以随意设置。 尽管未强制实施,但强烈建议使用增加的版本号,因为如果尝试转换为代表较新数据的较低数据版本号,则可能会发生麻烦的复杂影响(包括数据丢失)。

应用数据仅在具有相同版本号的已安装应用之间漫游。 例如,版本 2 上的设备之间将相互转换数据,版本 3 上的设备之间将执行相同的操作,但运行版本 2 的设备与运行版本 3 的设备之间不会发生漫游。 如果在其他设备上安装使用多种版本号的新应用,新安装的应用将同步与最高版本号关联的应用数据。

测试和工具

请参阅关于漫游数据的重要说明。

开发人员可以锁定其设备,以触发漫游应用数据的同步。 如果应用数据在特定期限内未转换,请检查以下项目并确保:

  • 漫游数据不超过最大大小(有关详细信息,请参阅 RoamingStorageQuota)。
  • 文件已关闭并正确释放。
  • 至少有两个设备运行同一版本的应用。

注册以在漫游数据更改时接收通知

请参阅关于漫游数据的重要说明。

若要使用漫游应用数据,需要注册漫游数据更改并取回漫游数据容器,以便可以读取和写入设置。

  1. 注册以在漫游数据更改时接收通知。

    DataChanged 事件在漫游数据更改时通知你。 此示例将 DataChangeHandler 设置为漫游数据更改的处理程序。

void InitHandlers()
    {
       Windows.Storage.ApplicationData.Current.DataChanged += 
          new TypedEventHandler<ApplicationData, object>(DataChangeHandler);
    }

    void DataChangeHandler(Windows.Storage.ApplicationData appData, object o)
    {
       // TODO: Refresh your data
    }
  1. 获取应用设置和文件的容器。

    使用 ApplicationData.RoamingSettings 属性获取设置,使用 ApplicationData.RoamingFolder 属性获取文件。

Windows.Storage.ApplicationDataContainer roamingSettings = 
        Windows.Storage.ApplicationData.Current.RoamingSettings;
    Windows.Storage.StorageFolder roamingFolder = 
        Windows.Storage.ApplicationData.Current.RoamingFolder;

创建和取回漫游设置

请参阅关于漫游数据的重要说明。

使用 ApplicationDataContainer.Values 属性访问我们在上一部分中获取的 roamingSettings 容器中的设置。 此示例创建一个名为 exampleSetting 的简单设置,和一个名为 composite 的复合值。

// Simple setting

roamingSettings.Values["exampleSetting"] = "Hello World";
// High Priority setting, for example, last page position in book reader app
roamingSettings.values["HighPriority"] = "65";

// Composite setting

Windows.Storage.ApplicationDataCompositeValue composite = 
    new Windows.Storage.ApplicationDataCompositeValue();
composite["intVal"] = 1;
composite["strVal"] = "string";

roamingSettings.Values["exampleCompositeSetting"] = composite;

此示例取回了刚刚创建的设置。

// Simple setting

Object value = roamingSettings.Values["exampleSetting"];

// Composite setting

Windows.Storage.ApplicationDataCompositeValue composite = 
   (Windows.Storage.ApplicationDataCompositeValue)roamingSettings.Values["exampleCompositeSetting"];

if (composite == null)
{
   // No data
}
else
{
   // Access data in composite["intVal"] and composite["strVal"]
}

创建和取回漫游文件

请参阅关于漫游数据的重要说明。

若要在漫游应用数据存储中创建和更新文件,请使用文件 API,例如 Windows.Storage.StorageFolder.CreateFileAsyncWindows.Storage.FileIO.WriteTextAsync。 此示例在 roamingFolder 容器中创建一个名为 dataFile.txt 的文件,并将当前日期和时间写入文件。 CreationCollisionOption 枚举中的 ReplaceExisting 值指示替换文件(如果其已存在)。

async void WriteTimestamp()
{
   Windows.Globalization.DateTimeFormatting.DateTimeFormatter formatter = 
       new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("longtime");

   StorageFile sampleFile = await roamingFolder.CreateFileAsync("dataFile.txt", 
       CreationCollisionOption.ReplaceExisting);
   await FileIO.WriteTextAsync(sampleFile, formatter.Format(DateTimeOffset.Now));
}

若要在漫游应用数据存储中打开和读取文件,请使用文件 API,例如 Windows.Storage.StorageFolder.GetFileAsyncWindows.Storage.StorageFile.GetFileFromApplicationUriAsyncWindows.Storage.FileIO.ReadTextAsync。 本示例打开在上一部分中创建的 dataFile.txt 文件,并从文件读取日期。 有关从各种位置加载文件资源的详细信息,请参阅如何加载文件资源

async void ReadTimestamp()
{
   try
   {
      StorageFile sampleFile = await roamingFolder.GetFileAsync("dataFile.txt");
      String timestamp = await FileIO.ReadTextAsync(sampleFile);
      // Data is contained in timestamp
   }
   catch (Exception)
   {
      // Timestamp not found
   }
}

临时应用数据

临时应用数据存储的工作方式类似于缓存。 其文件不会漫游,可以随时删除。 系统维护任务可以随时自动删除存储在此位置的数据。 用户还可以使用磁盘清理从临时数据存储中清除文件。 临时应用数据可用于在应用会话期间存储临时信息。 不能保证此数据在应用会话结束后仍被保留,因为系统可能会根据需要回收已用的空间。 位置可通过 temporaryFolder 属性获取。

取回临时数据容器

使用 ApplicationData.TemporaryFolder 属性获取文件。 后续步骤使用此步骤中的 temporaryFolder 变量。

Windows.Storage.StorageFolder temporaryFolder = ApplicationData.Current.TemporaryFolder;

创建和读取临时文件

若要在临时应用数据存储中创建和更新文件,请使用文件 API,例如 Windows.Storage.StorageFolder.CreateFileAsyncWindows.Storage.FileIO.WriteTextAsync。 此示例在 temporaryFolder 容器中创建一个名为 dataFile.txt 的文件,并将当前日期和时间写入文件。 CreationCollisionOption 枚举中的 ReplaceExisting 值指示替换文件(如果其已存在)。

async void WriteTimestamp()
{
   Windows.Globalization.DateTimeFormatting.DateTimeFormatter formatter = 
       new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("longtime");

   StorageFile sampleFile = await temporaryFolder.CreateFileAsync("dataFile.txt", 
       CreateCollisionOption.ReplaceExisting);
   await FileIO.WriteTextAsync(sampleFile, formatter.Format(DateTimeOffset.Now));
}

若要在临时应用数据存储中打开和读取文件,请使用文件 API,例如 Windows.Storage.StorageFolder.GetFileAsyncWindows.Storage.StorageFile.GetFileFromApplicationUriAsyncWindows.Storage.FileIO.ReadTextAsync。 本示例打开在上一步中创建的 dataFile.txt 文件,并从文件读取日期。 有关从各种位置加载文件资源的详细信息,请参阅如何加载文件资源

async void ReadTimestamp()
{
   try
   {
      StorageFile sampleFile = await temporaryFolder.GetFileAsync("dataFile.txt");
      String timestamp = await FileIO.ReadTextAsync(sampleFile);
      // Data is contained in timestamp
   }
   catch (Exception)
   {
      // Timestamp not found
   }
}

使用容器组织应用数据

为了帮助你组织应用数据设置和文件,可以创建容器(由 ApplicationDataContainer 对象表示),而不是直接使用目录。 可以将容器添加到本地、漫游和临时应用数据存储。 容器最多可嵌套 32 个级别。

若要创建设置容器,请调用 ApplicationDataContainer.CreateContainer 方法。 本示例创建一个名为 exampleContainer 的本地设置容器,并添加名为 exampleSetting 的设置。 ApplicationDataCreateDisposition 枚举中的 Always 值表示,如果容器尚不存在,则会创建容器。

Windows.Storage.ApplicationDataContainer localSettings = 
    Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder = 
    Windows.Storage.ApplicationData.Current.LocalFolder;

// Setting in a container
Windows.Storage.ApplicationDataContainer container = 
   localSettings.CreateContainer("exampleContainer", Windows.Storage.ApplicationDataCreateDisposition.Always);

if (localSettings.Containers.ContainsKey("exampleContainer"))
{
   localSettings.Containers["exampleContainer"].Values["exampleSetting"] = "Hello Windows";
}

删除应用设置和容器

若要删除应用不再需要的简单设置,可使用 ApplicationDataContainerSettings.Remove 方法。 此示例删除之前创建的 exampleSetting 本地设置。

Windows.Storage.ApplicationDataContainer localSettings = 
    Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder = 
    Windows.Storage.ApplicationData.Current.LocalFolder;

// Delete simple setting

localSettings.Values.Remove("exampleSetting");

若要删除复合设置,请使用 ApplicationDataCompositeValue.Remove 方法。 此示例删除早前示例中创建的本地 exampleCompositeSetting 复合设置。

Windows.Storage.ApplicationDataContainer localSettings = 
    Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder = 
    Windows.Storage.ApplicationData.Current.LocalFolder;

// Delete composite setting

localSettings.Values.Remove("exampleCompositeSetting");

若要删除容器,请调用 ApplicationDataContainer.DeleteContainer 方法。 此示例删除之前创建的本地 exampleContainer 设置容器。

Windows.Storage.ApplicationDataContainer localSettings = 
    Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder = 
    Windows.Storage.ApplicationData.Current.LocalFolder;

// Delete container

localSettings.DeleteContainer("exampleContainer");

对应用数据进行版本控制

可以选择对应用的数据进行版本控制。 这样就可以创建应用的未来版本,确保更改其应用数据的格式时,不会导致应用早期版本的兼容性问题。 应用检查数据存储中的应用数据版本,如果版本小于应用所需的版本,应用应将应用数据更新为新格式并更新版本。 有关详细信息,请参阅 Application.Version 属性和 ApplicationData.SetVersionAsync 方法。