Ранее мы уже сталкивались с некоторыми моментами сохранения данных в телефоне, теперь рассмотрим этот вопрос более подробно.
В программе на Windows Phone 8.1 мы можем сохранить данные в сериализованном виде, например, в формате xml или json.
На устройстве Windows Phone 8.1 каждому приложению отводится свое место в папке Local. Чтобы получить этот хранилище в приложении, мы можем использовать объект Windows.Storage.ApplicationData.Current.LocalFolder. Этот объект обладает рядом методов для чтения/записи файлов, позволяя, тем самым, управлять сохраненными данными. Но среди его методов можно выделить следующие два:
OpenStreamForWriteAsync() - сохраняет данные в файл
OpenStreamForReadAsync() - считывает данные из файла
Первый метод принимает два параметра: имя файла и перечисление Windows.Storage.CreationCollisionOption. Данное перечисление может иметь следующие значения:
OpenIfExists: предполагает открытие файла
FailIfExists: генерирует исключение, если файл с таким именем уже существует
GenerateUniqueName: генерирует новый файл с уникальным именем, если заданный файл уже существует
ReplaceExisting: перезаписывает имеющийся файл
А второй принимает имя файла для чтения.
Для примера создадим новое приложение по типу Blank App. И сначала добавим в проект модель, которую мы будем сохранять и затем восстанавливать. Пусть это будет простенький класс User:
public class User { public string Name { get; set; } public string Surname { get; set; } public string Company { get; set; } }
Определим на главной странице MainPage.xaml следующую разметку:
<Page x:Class="SerializeDataApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:SerializeDataApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid> <StackPanel> <TextBlock x:Name="infoBlock" Text="Введите данные" /> <TextBox x:Name="nameBox" PlaceholderText="Имя" /> <TextBox x:Name="surnameBox" PlaceholderText="Фамилия" /> <TextBox x:Name="companyBox" PlaceholderText="Компания" /> <StackPanel Orientation="Horizontal"> <Button x:Name="saveButton" Content="Сохранить" Click="saveButton_Click" /> <Button x:Name="getButton" Content="Извлечь" Click="getButton_Click" /> </StackPanel> </StackPanel> </Grid> </Page>
У нас есть три текстовых поля для ввода данных и две кнопки, которые будет сохранять и восстанавливать данные.
Опеределим в файле mainPage.xaml.cs обработчики для этих кнопок:
private async void saveButton_Click(object sender, RoutedEventArgs e) { await writeXMLAsync(); } private async void getButton_Click(object sender, RoutedEventArgs e) { await readXMLAsync(); } private async Task writeXMLAsync() { User user = new User(); user.Name = nameBox.Text; user.Surname = surnameBox.Text; user.Company = companyBox.Text; var serializer = new DataContractSerializer(typeof(User)); using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync( "data.xml", CreationCollisionOption.ReplaceExisting)) { serializer.WriteObject(stream, user); } infoBlock.Text = "Данные сохранены"; } private async Task readXMLAsync() { var serializer = new DataContractSerializer(typeof(User)); // проверка наличия файла bool existed = await FileExists(ApplicationData.Current.LocalFolder, "data.xml"); if (existed) { using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync("data.xml")) { User user = (User)serializer.ReadObject(stream); nameBox.Text = user.Name; surnameBox.Text = user.Surname; companyBox.Text = user.Company; } } } // проверка наличия файла public async Task<bool> FileExists(StorageFolder folder, string fileName) { return (await folder.GetFilesAsync()).Any(x => x.Name == fileName); }
Кроме объекта ApplicationData.Current.LocalFolder здесь используется другой ключевой класс - класса-сериализатор DataContractSerializer. Он позволяет сериализовать данные в файл xml, а также потом восстановить данные из этого файла.
При создании объекта класса DataContractSerializer мы задаем ему тип объекта, с которым ему необходимо работать: new DataContractSerializer(typeof(User))
.
Если бы мы сохраняли список объектов User, то соответственно могли бы указать new DataContractSerializer(typeof(List<User>))
С помощью метода WriteObject()
объект DataContractSerializer сохраняет данные, а с помощью метода ReadObject()
извлекает.
Этими методами функциональность класса не ограничивается, но они являются основными для механизма сериализации и десериализации.
И теперь запустив приложение и введя данные, мы можем по нажатию кнопки сохранить их в памяти смартфона. Затем через некоторое время перезапустив приложение мы можем восстановить ранее сохраненные данные.
И если мы захотим вместо xml-формата использовать json, тогда мы можем использовать класс DataContractJsonSerializer, действие которого аналогично классу DataContractSerializer. Например, сохранение:
private async Task writeAsync() { User user = new User(); user.Name = nameBox.Text; user.Surname = surnameBox.Text; user.Company = companyBox.Text; var serializer = new DataContractJsonSerializer(typeof(User)); using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync( "data.json", CreationCollisionOption.ReplaceExisting)) { serializer.WriteObject(stream, user); } }