⬆️ ⬇️

Work with data in WinRT. Part 1. Storing Settings and Files

In WinRT, work with data and the file system has changed and it is slightly different from both desktop .NET and Silverlight.



To access user files in the system, you need appropriate permissions and you need to use contracts and extensions to work with files (which will be discussed in a separate article). However, each application has access to isolated storage for storing service data and settings. All that is needed to store data is in the Windows.Storage namespace in the ApplicationData object.



In this article we will consider working with the following objects:

')

Store simple data in LocalSettings and RoamingSettings. (Storage of simple data)



Storage of binary data in LocalFolder, TemporaryFolder, RoamingFolder. (File storage in file system)



Features of working with RoamingSettings and RoamingFolder (Storing data in the cloud. Synchronize data between devices).



Versioning of data in roaming.



Direct data access via Uri.



The next part will be considered work with the database.





The official example for working with local data can be downloaded at: code.msdn.microsoft.com/windowsapps/ApplicationData-sample-fb043eb2



This article will look at an example of how local data works with FileStorage.zip.



1. Storage of simple data in LocalSettings and RoamingSettings



Working with LocalSettings and RoamingSettings is identical. Distinctive features of RoamingSettings will be discussed below.



First of all, these objects are intended for storing simple data with simple types. It can store data of type string, bool, int, float, etc. These objects are useful for storing settings like sound volume, etc.



The API is implemented very simply. The following code saves the text with the “customKey” key:



ApplicationData.Current.LocalSettings.Values["customKey"] = "mytext"; 


Reading the data is as simple as saving (since values ​​of the object type must be transferred to the original type):

 var customText = (string) ApplicationData.Current.LocalSettings.Values["customKey"]; 


It is also advisable to check the presence of the key before extracting it, so as not to get a NullReferenceException error for meaningful data types (bool, int, float, etc.).



var settings = ApplicationData.Current.LocalSettings;

if (settings.Values.ContainsKey ("pageNumber"))

{

var number = (int) settings.Values ​​["pageNumber"];

}



Often we need to store more complex data types and / or binary data. In this case, we can use xFolder objects.



2. Storage of binary data in LocalFolder, TemporaryFolder, RoamingFolder.



xFolder objects are designed to store data in the file system. Working with them is almost identical with small features.



LocalFolder is intended for storing service files necessary for an application, such as a database or for data downloaded from a network that must be on the client.



TemproryFolder is well suited for temporary data. For example, for a social networking client application, this folder is well suited for caching photos.



RoamingFolder as well as RoamingSettings can be used for data that needs to be synchronized between devices and / or stored in the cloud. The work with it will be discussed in detail later, but it is possible to store small data (up to 100 kb) in it.



To work with files, you can also use methods of the FileIO object, which simplifies working with data.



For example, the following code creates a text file my.txt with the contents of Hello! World!



 var storageFolder = ApplicationData.Current.LocalFolder; var file = await storageFolder.CreateFileAsync("my.txt", CreationCollisionOption.ReplaceExisting); await FileIO.WriteTextAsync(file, "Hello! World!"); 


Similarly, you can read a text file:



 var storageFolder = ApplicationData.Current.LocalFolder; var file = await storageFolder.GetFileAsync("my.txt"); var text = await FileIO.ReadTextAsync(file); 


In those cases when we need to save complex data types, we can use some kind of serializer. For example, DataContractSerializer (in the System.Runtime.Serialization namespace) or third-party library Json.net.



In the example attached to the article there is an example of saving and reading a book using the Json.NET library:



 public static async Task Save(Book book) { var serializedString = JsonConvert.SerializeObject(book); var storageFolder = ApplicationData.Current.LocalFolder; var file = await storageFolder.CreateFileAsync("book.dat", CreationCollisionOption.ReplaceExisting); await FileIO.WriteTextAsync(file, serializedString); } public static async Task<Book> GetBook() { var file = await ApplicationData.Current.LocalFolder.GetFileAsync("book.dat"); var serializedString = await FileIO.ReadTextAsync(file); return await JsonConvert.DeserializeObjectAsync<Book>(serializedString); } 


Now that we have looked at how to work with Settings and Folder, we can consider the features when working with Roaming data.



3. Features of working with RoamingSettings and RoamingFolder



RoamingSettings and RoamingFolder are designed to store small amounts of data in the cloud. It should not attempt to store the full database of your application. For example, if you have an application for reading books, you should not try to store the texts of books in it, instead you can store the last open file and the page that the user is reading now. For the game, you can store the current state of passing the game (for example, information about unlocked levels).



These objects provide a free opportunity to keep passing the game, not only between reinstalling applications, but also between different devices, without having to maintain your own server infrastructure!



In addition, as mentioned above, since the data that is stored in these objects is stored between application installations, you should carefully design the logic for working with data in these storages, since if your application, for example, falls with incorrect values ​​in these objects, then it will continue to fall even after reinstallation. That can lead to the fact that the user will lose any opportunity to work with your application.



3.1. Restrictions


The amount of available data is limited and its value can be obtained from the RoamingStorageQuota property (the value is specified in kilobytes - the default is 100 kb)



 ApplicationData.Current.RoamingStorageQuota 


Also, when saving data to the RoamingFolder, you cannot use spaces in file names.



3.2. Sync time


When designing an application that works through the Roaming Folder, it is necessary to take into account that the time of data synchronization between devices is about 10-15 minutes. However, for RoamingSettings there is a service key that should be used for data with high sync priority:



 HighPriority 




Data synchronization time for this key is somewhere 15-30 seconds.



 ApplicationData.Current.LocalSettings.Values["HighPriority"] = "high priority data"; 


You can also intercept the DataChanged: data change event while the application is running.



 ApplicationData.Current.DataChanged += Current_DataChanged; 


Since the event is not called in the UI thread, updating the UI should be done through the dispatcher:



 void Current_DataChanged(ApplicationData sender, object args) { Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { MyTextBox.Text = (string)ApplicationData.Current.RoamingSettings.Values["HighPriority"]; }); } 


To debug an application, we can call the ApplicationData.Current.SignalDataChanged () method; which will trigger the DataChanged event.



What to do when, in the new version of the application, a new data structure is required, which is not compatible with the data structure of the previous application?



4. Versioning of data in roaming.



Any application that continues to evolve over time requires a new data structure. For data that is stored locally, we can provide our own version control and update mechanisms.



For data in roaming, the potential problem is that if in new applications we can provide for the processing logic of the old format, then the already installed and working applications will not be able to process the data of the new format.



WinRT provides a ready-made API for splitting data into different versions. Roaming data in the application will receive data only from versions with the same number. The DataChanged event is triggered only in those applications where the identical version of data is installed.



The current version can be obtained from the ApplicationData.Version property:



 ApplicationData.Current.Version 


By default, the version number is 0.



It is strongly recommended to initially provide for the possibility of changes in the future and start not with the default version but with version 1.



You can install the new version of the data through the SetVersionAsync method:



 await ApplicationData.Current.SetVersionAsync(versinoNumber, UpgradeToVersionHandler); TextBlockDataVersion.Text = ApplicationData.Current.Version.ToString(); 




Where:



versionNumber - integer version number



UpgradeToVersionHandler - data update handler:



 private void UpgradeToVersionHandler(SetVersionRequest setversionrequest) { var defferal = setversionrequest.GetDeferral(); if (setversionrequest.DesiredVersion > setversionrequest.CurrentVersion) { //UpgradeCodeFromOldToNewVersion(); } defferal.Complete(); } 


Since when we install a new version of the application, we also need to update the data, we must use the GetDefferral () method to ensure that the application is not closed at the time of updating the data.



As with roaming data, the data version remains even after reinstalling the application. Version number is not synchronized between devices (For each device, its own version number).



Often, applications need to directly access data in a folder. In the next section, we will look at how to do this.



5. Direct access to data through Uri and Path.





WinRT has prefixes for direct access to data. To do this, you can use the following prefixes:



ms-appx: /// - access files included in the project.



ms-appdata: /// local / - access files stored in the LocalFolder folder



ms-appdata: /// roaming / - access to files saved in the RoamingFolder folder



ms-appdata: /// temp / - access to files in the TemporaryFolder folder



In official examples there is an example of access to pictures using these prefixes:



 LocalImage.Source = new BitmapImage(new Uri("ms-appdata:///local/appDataLocal.png")); RoamingImage.Source = new BitmapImage(new Uri("ms-appdata:///roaming/appDataRoaming.png")); TempImage.Source = new BitmapImage(new Uri("ms-appdata:///temp/appDataTemp.png")); 


If necessary, we can also access the folder where the application is stored. The path to the folder can be obtained from the Path property for all xFolder objects. For example, the path to the local folder can be obtained from the property:



 ApplicationData.Current.LocalFolder.Path 


In this case, the path to the folder looks like this:



c: \ users \ UserName \ AppData \ Local \ Packages \ e965c8d4-0dff-4f2e-8340-24041aabca05_5mvwcwnjebzdj \ LocalState \



Where



UserName - username in the system



e965c8d4-0dff-4f2e-8340-24041aabca05 - application identifier.



Accordingly, the full path to the file in this folder can be obtained either by simple string concatenation or using the Path.Combine helper method (System.IO Namespace). So, the path to the file my.txt will look like this:



 var fullPath=Path.Combine(ApplicationData.Current.RoamingFolder.Path, "my.txt"); 


Direct file access can be conveniently used to work with databases to indicate the path to the database file, the work with which will be discussed in the next section.



Results



As we can see, Microsoft has significantly simplified the ability to work with data by providing ready-made tools for storing local and temporary data and providing a simple and free mechanism for synchronizing application state between devices (which can be used as a cloud backup for small data, if necessary). Now you can provide users with the opportunity to save the passage of their favorite game. :)

Source: https://habr.com/ru/post/151467/



All Articles