Сохранение данных

Последнее обновление: 31.10.2015

Ранее мы уже сталкивались с некоторыми моментами сохранения данных в телефоне, теперь рассмотрим этот вопрос более подробно.

В программе на 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);
    }
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850