Хранение и получение параметров и других данных приложения
Данные приложения являются изменяемыми данными, которые создаются и управляются конкретным приложением. К ним относятся сведения о состоянии среды выполнения, параметры приложения, пользовательские настройки, справочная информация (например, определения слов в приложении-словаре) и другие параметры. Данные приложения отличаются от пользовательских данных, данных, которые пользователь создает и управляет при использовании приложения. Данные пользователя включают файлы документов или мультимедиа, расшифровки сообщений электронной почты или записи базы данных, которые содержат содержимое, созданное пользователем. Пользовательские данные могут быть полезными или значимыми для нескольких приложений. Часто это данные, которые пользователь хочет управлять или передавать как сущность независимо от самого приложения, например документа.
Важно отметить данные приложения: время существования данных приложения привязано к времени существования приложения. Если приложение удалено, все данные приложения будут потеряны в результате. Не используйте данные приложения для хранения пользовательских данных или каких-либо данных, которые пользователи могут воспринимать как ценные и незаменимые. Мы рекомендуем использовать библиотеки пользователя и Microsoft OneDrive для хранения таких сведений. Данные приложения идеально подходят для хранения пользовательских настроек, параметров и избранного для конкретного приложения.
Типы данных приложения
Существует два типа данных приложения: параметры и файлы.
Настройки
Используйте параметры для хранения параметров пользователя и сведений о состоянии приложения. API данных приложения позволяет легко создавать и извлекать параметры (мы рассмотрим некоторые примеры далее в этой статье).
Ниже приведены типы данных, которые можно использовать для параметров приложения:
- UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double
- Boolean
- Char16, String
- DateTime, TimeSpan
- Для C#/.NET используйте: System.DateTimeOffset, System.TimeSpan
Files
Используйте файлы для хранения двоичных данных или включения собственных настраиваемых сериализованных типов.
Хранение данных приложения в хранилищах данных приложения
Когда приложение установлено, система предоставляет ему собственные хранилища данных для пользовательских параметров и файлов. Вам не нужно знать, где или как эти данные существуют, так как система отвечает за управление физическим хранилищем, обеспечивая изоляцию данных от других приложений и других пользователей. Система также сохраняет содержимое этих хранилищ данных, когда пользователь устанавливает обновление в приложение и удаляет содержимое этих хранилищ данных полностью и чисто при удалении приложения.
В хранилище данных приложения каждое приложение имеет системные корневые каталоги: один для локальных файлов, один для перемещаемых файлов и один для временных файлов. Приложение может добавлять новые файлы и новые контейнеры в каждый из этих корневых каталогов.
Данные локального приложения
Данные локального приложения должны использоваться для любых сведений, которые необходимо сохранить между сеансами приложений и не подходят для перемещаемых данных приложения. Данные, которые не применимы на других устройствах, также должны храниться здесь. Нет общего ограничения размера для локальных данных, хранящихся. Используйте локальное хранилище данных приложения для данных, которые не имеет смысла перемещать и использовать для больших наборов данных.
Получение локального хранилища данных приложения
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.служба хранилища. служба хранилища Folder.CreateFileAsync и Windows.служба хранилища. FileIO.WriteTextAsync. В этом примере создается файл с именем dataFile.txt в контейнере localFolder и записывается текущая дата и время в файл. Значение ReplaceExisting из перечисления CreationCollisionOption указывает, чтобы заменить файл, если он уже существует.
async void WriteTimestamp()
Чтобы открыть и прочитать файл в локальном хранилище данных приложения, используйте API-интерфейсы файлов, такие как Windows.служба хранилища. служба хранилища Folder.GetFileAsync, Windows.служба хранилища. служба хранилища File.GetFileFromApplicationUriAsync и Windows.служба хранилища. 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 и интернет-решения.
Следующая документация относится к Windows 10 версии 1909 и более низкой.
При использовании перемещаемых данных в приложении пользователи могут легко синхронизировать данные приложения на нескольких устройствах. Если пользователь устанавливает приложение на нескольких устройствах, ОС сохраняет данные приложения в синхронизации, уменьшая объем работы установки, которую пользователь должен сделать для вашего приложения на втором устройстве. Перемещение также позволяет пользователям продолжать задачу, например создание списка, вправо, где они уволились даже на другом устройстве. ОС реплика перемещает данные в облако при обновлении и синхронизирует данные с другими устройствами, на которых установлено приложение.
Перемещаемые данные для приложения доступны в облаке, если доступ к нему осуществляется пользователем с какого-то устройства в течение требуемого интервала времени. Если пользователь не запускает приложение дольше этого интервала времени, его перемещаемые данные удаляются из облака. Если пользователь удаляет приложение, его перемещаемые данные не удаляются из облака автоматически, он сохраняется. Если пользователь переустановит приложение в течение интервала времени, перемещаемые данные синхронизируются из облака.
Перемещаемые данные выполняются и не выполняются
- Используйте роуминг для пользовательских настроек и настроек, ссылок и небольших файлов данных. Например, используйте роуминг для сохранения предпочтения цвета фона пользователя на всех устройствах.
- Используйте перемещение, чтобы пользователи продолжали задачу на разных устройствах. Например, перемещайте данные приложения, такие как содержимое черновика электронной почты или недавно просматриваемую страницу в приложении чтения.
- Обработайте событие DataChanged , обновив данные приложения. Это событие возникает, когда данные приложения только что завершили синхронизацию из облака.
- Перемещайте ссылки на содержимое, а не необработанные данные. Например, перемещайте URL-адрес, а не содержимое веб-статьи.
- Для важных параметров времени используйте параметр HighPriority, связанный сроумингом Параметры.
- Не перемещайте данные приложения, относящиеся к устройству. Некоторые сведения имеют отношение только локально, например имя пути к локальному ресурсу файла. Если вы решите перемещать локальную информацию, убедитесь, что приложение может восстановиться, если сведения не действительны на дополнительном устройстве.
- Не перемещайте большие наборы данных приложения. Существует ограничение на объем данных приложения, которые может перемещать приложение; используйте свойство Roaming служба хранилища Quota, чтобы получить это максимальное значение. Если приложение достигает этого ограничения, данные не могут перемещаться до тех пор, пока размер хранилища данных приложения больше не превышает предел. При разработке приложения рассмотрите, как поместить привязку к большим данным, чтобы не превышать предел. Например, если для сохранения игрового состояния требуется 10 КБ каждой из них, приложение может разрешить только 10 игр.
- Не используйте роуминг для данных, основанных на мгновенной синхронизации. Windows не гарантирует мгновенной синхронизации; Перемещение может быть значительно отложено, если пользователь находится в автономном режиме или в сети с высокой задержкой. Убедитесь, что пользовательский интерфейс не зависит от мгновенной синхронизации.
- Не используйте перемещение для часто изменяющихся данных. Например, если ваше приложение отслеживает часто изменяющиеся сведения, например положение в песне на секунду, не сохраняйте это как перемещаемые данные приложения. Вместо этого выберите менее частое представление, которое по-прежнему обеспечивает хороший пользовательский интерфейс, как и в настоящее время играющая песня.
Предварительные требования для роуминга
Любой пользователь может воспользоваться перемещаемыми данными приложения, если он использует учетную запись Майкрософт для входа на свое устройство. Однако пользователи и администраторы групповой политики могут отключить перемещаемые данные приложения на устройстве в любое время. Если пользователь принимает решение не использовать учетную запись Майкрософт или отключает возможности перемещения данных, он по-прежнему сможет использовать данные вашего приложения, но данные приложения будут локальными на каждом устройстве.
Данные, сохраненные в PasswordVault, перемещаются, только если пользователь присвоил своему устройству статус доверенного. Если устройство не является доверенным, данные, защищенные в этом хранилище, не будут перемещаться.
Разрешение конфликтов
Данные перемещаемого приложения не предназначены для одновременного использования на нескольких устройствах одновременно. Если во время синхронизации возникает конфликт, так как на двух устройствах была изменена определенная единица данных, система всегда будет предпочитать значение, записанное последнее. Это гарантирует, что приложение использует самые актуальные сведения. Если единица данных является составной, разрешение конфликтов по-прежнему будет происходить на уровне единицы установки, что означает, что составной с последним изменением будет синхронизирован.
Когда записывать данные
В зависимости от ожидаемого времени существования параметра данные должны записываться в разное время. Нечасто или медленно изменяя данные приложения должны быть записаны немедленно. Однако данные приложения, которые часто изменяются, следует периодически записывать только через регулярные интервалы (например, каждые 5 минут), а также при приостановке приложения. Например, музыкальное приложение может записывать параметры текущей композиции в начале воспроизведения новой композиции, при этом фактическая позиция в песне должна записываться только при приостановке.
Чрезмерная защита использования
Система имеет различные механизмы защиты, чтобы избежать неправильного использования ресурсов. Если данные приложения не переходят должным образом, скорее всего, устройство временно ограничено. Ожидание некоторого времени обычно решает эту ситуацию автоматически, и никаких действий не требуется.
Управление версиями
Данные приложения могут использовать управление версиями для обновления одной структуры данных до другой. Номер версии отличается от версии приложения и может быть задан. Хотя и не применяется, настоятельно рекомендуется использовать дополнительные номера версий, так как нежелательные осложнения (включая потерю данных)могут возникнуть при попытке перейти на более низкий номер версии данных, представляющий новые данные.
Данные приложения перемещается только между установленными приложениями с одинаковым номером версии. Например, устройства в версии 2 переключят данные между собой и устройствами версии 3 будут делать то же самое, но перемещение между устройством под управлением версии 2 и устройством под управлением версии 3 не будет. При установке нового приложения, которое использовало различные номера версий на других устройствах, только что установленное приложение синхронизирует данные приложения, связанные с самым высоким номером версии.
Тестирование и средства
Разработчики могут заблокировать свое устройство для активации синхронизации перемещаемых данных приложения. Если кажется, что данные приложения не переходят в течение определенного интервала времени, проверка следующие элементы и убедитесь, что:
- Перемещаемые данные не превышают максимальный размер (см. сведения о роуминге служба хранилища Quota).
- Файлы закрыты и освобождены должным образом.
- Существует по крайней мере два устройства с одной и той же версией приложения.
Регистрация для получения уведомления при изменении перемещаемых данных
Чтобы использовать данные перемещаемого приложения, необходимо зарегистрировать для изменения перемещаемых данных и получить перемещаемые контейнеры данных, чтобы можно было считывать и записывать параметры.
- Зарегистрируйтесь для получения уведомления при изменении перемещаемых данных. Событие DataChanged уведомляет вас об изменении перемещаемых данных. Этот пример задает DataChangeHandler обработчик для изменения перемещаемых данных.
void InitHandlers() < Windows.Storage.ApplicationData.Current.DataChanged += new TypedEventHandler(DataChangeHandler); > void DataChangeHandler(Windows.Storage.ApplicationData appData, object o) < // TODO: Refresh your data >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.служба хранилища. служба хранилища Folder.CreateFileAsync и Windows.служба хранилища. FileIO.WriteTextAsync. В этом примере создается файл с именем dataFile.txt в контейнере roamingFolder и записывается текущая дата и время в файл. Значение ReplaceExisting из перечисления CreationCollisionOption указывает, чтобы заменить файл, если он уже существует.
async void WriteTimestamp()
Чтобы открыть и прочитать файл в хранилище данных перемещаемого приложения, используйте API-интерфейсы файлов, такие как Windows.служба хранилища. служба хранилища Folder.GetFileAsync, Windows.служба хранилища. служба хранилища File.GetFileFromApplicationUriAsync и Windows.служба хранилища. 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 >>Временные данные приложения
Временное хранилище данных приложения работает как кэш. Его файлы не перемещаются и могут быть удалены в любое время. Задача обслуживания системы может автоматически удалять данные, хранящиеся в этом расположении в любое время. Пользователь также может очистить файлы из временного хранилища данных с помощью очистки диска. Временные данные приложения можно использовать для хранения временных сведений во время сеанса приложения. Нет никаких гарантий, что эти данные будут сохраняться после окончания сеанса приложения, так как система может освободить используемое пространство при необходимости. Расположение доступно через временное свойствоFolder .
Получение временного контейнера данных
Используйте свойство ApplicationData.TemporaryFolder для получения файлов. Следующие шаги используют temporaryFolder переменную из этого шага.
Windows.Storage.StorageFolder temporaryFolder = ApplicationData.Current.TemporaryFolder;Создание и чтение временных файлов
Чтобы создать и обновить файл во временном хранилище данных приложения, используйте API-интерфейсы файлов, такие как Windows.служба хранилища. служба хранилища Folder.CreateFileAsync и Windows.служба хранилища. FileIO.WriteTextAsync. В этом примере создается файл с именем dataFile.txt в контейнере temporaryFolder и записывается текущая дата и время в файл. Значение ReplaceExisting из перечисления CreationCollisionOption указывает, чтобы заменить файл, если он уже существует.
async void WriteTimestamp()
Чтобы открыть и прочитать файл во временном хранилище данных приложения, используйте API-интерфейсы файлов, такие как Windows.служба хранилища. служба хранилища Folder.GetFileAsync, Windows.служба хранилища. служба хранилища File.GetFileFromApplicationUriAsync и Windows.служба хранилища. 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 . Значение Always из перечисления ApplicationDataCreateDisposition указывает, что контейнер создается, если он еще не существует.
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"))Удаление параметров и контейнеров приложений
Чтобы удалить простой параметр, который больше не требуется приложению, используйте ApplicationDataContainer Параметры. Удалить метод. В этом примере удаляется локальный 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");Управление версиями данных приложения
Связанные статьи
- Windows.Storage.ApplicationData
- Windows.Storage.ApplicationData.RoamingSettings
- Windows.Storage.ApplicationData.RoamingFolder
- Windows.Storage.ApplicationData.RoamingStorageQuota
- Windows.Storage.ApplicationDataCompositeValue
Как хранить данные программы?
Подскажите как локально хранить данные программы(не в БД).Пара «значение-ключ».Нужно будет быстро и просто считывать их и перезаписывать.Думал про excel но не знаю будет ли работать есть ли у пользователя нет офиса.Подскажите ещё какие-то варианты
- Вопрос задан более трёх лет назад
- 726 просмотров
Комментировать
Решения вопроса 1
Завист от размера, если много данных то EF+sql lite, если мало то сериализуйте словарь и сохраните в файл:
var str = JsonConvert.SerializeObject(new Dictionary < < "key","value">, < "key2","value2">>); File.WriteAllText("config.json", str); str = File.ReadAllText("config.json"); var dict = JsonConvert.DeserializeObject(str); Ответ написан более трёх лет назад
Комментировать
Нравится 1 Комментировать
Хранение данных, XML, HTML
Этим уроком мы начинаем блок курса, посвященный тому, как в реальном мире хранятся данные. В следующих уроках мы рассмотрим форматы данных XML, JSON и познакомимся с базами данных.
План урока
- Как по-человечески хранить данные
- Формат данных XML
- Чтение XML в Ruby
- Немного про HTML
Хранение данных для программ
Программы работают с информацией, как человек с пищей — создают, готовят, потребляют, перерабатывают, показывают. Для того, чтобы программам (и программистам) было удобнее с ней работать, информацию нужно как-то хранить, в каком-то удобном виде предоставлять пользователям или другими программам.

Информация бывает очень сложная. Нельзя просто взять и записать в всё в один файл, как попало. Чтобы избежать неразберихи, люди договариваются о стандартах: розетки, батарейки, usb-входы. Программисты — тем более люди, они договорились о форматах и способах хранения данных.
Цель любого формата — структурировать данные, чтобы с ними было проще эффективнее работать: чтобы сразу было понятно, где файл начинается, где хранится служебная информация, как в нём упакованы данные. Форматов и способов хранения данных много, в нашем курсе мы познакомимся с самыми актуальными: XML, JSON и базы данных.
Формат XML
XML — это способ представить любую информацию в виде древовидной структуры. В жизни очень часто человек организует информацию именно в виде дерева. Давайте представим, как могла бы быть в виде XML упакована информация из вашего аккаунта в какой-нибудь социальной сети:
Гоша Петя Типичный XML файл начинается с заголовка, в котором указывается версия XML и кодировка файла . Дальше идёт дерево так называемых тегов. Корень у дерева один. Так и в XML-файле корневой тег-контейнер (оборачивающий всё остальное) — один. В нашем случае .
Теги записываются в треугольных скобках и бывают открывающие (
) и закрывающие, в начале названия которых стоит слеш ( ). Если какой-то элемент XML-структуры состоит из двух таких тегов, то он называется контейнером, т.к. в нём могут находиться другие элементы:Если же у тега нет закрывающего, то такой тег содержит слеш в самом конце: ( ).
Ещё у тегов бывают атрибуты, а у атрибутов — значения. Пары атрибут-значение записываются с помощью знака равно: ( )
Также тег-контейнер может содержать внутри себя кроме других тегов просто обычный текст.
Я текст внутри тега "some_tag" Вот вкратце и всё, что вам сейчас нужно знать про формат хранения данных XML.
Какие именно теги будут в вашей структуре — уже определяете вы, XML лишь накладывает требования на структуру, которые мы описали выше. Скажем, нельзя открыть тег и не закрыть его, нельзя оставить открой треугольную скобку вот так
XML настолько популярен, что многие программы в нем хранят данные. Например, популярный редактор текста Microsoft Word: его файлы *.docx по сути являются zip-архивами, если такой файл переименовать, поменяв расширение на .zip , то можно залезть внутрь такого архива и посмотреть, какие xml-файлы там лежат.
Проектируем программу для учета расходов
Давайте напишем программу, которая будет показывать, сколько на что мы потратили, а также выводить сумму всех трат за каждый месяц. Для этого нам как-то надо хранить данные о покупках.
Для начала давайте придумаем структуру, в которой мы будем описывать информацию о тратах. Этот XML-файл пока будем редактировать руками, а на следующем уроке научимся делать это с помощью программы.
expenses.xml :
Книжка по Ruby on Rails Петличка и провода Софтбокс + штатив Вот так мы будем хранить эти данные. Как вы видите, у нас есть корневой тег expenses , в него вложены теги expense (по одному на каждую трату), внутри каждого такого тега, текст с информацией о покупке, а в атрибутах date , amount и category соответственно дата, сумма и категория покупки.
Как читать формат XML в ruby
Для того, чтобы удобно работать с XML-файлами во всех современных языках есть парсеры. Парсер — это инструмент (чаще всего библиотека) для чтения данных из текста и представления их в удобной для работы с ними форме. Обычно их в каждом языке даже несколько. Какие-то быстрее, какие-то удобнее. Один из таких парсеров (REXML) уже встроен в Ruby (начиная с версии 1.9). Им и воспользуемся.
Программа для учёта расходов
Сейчас мы напишем программу, которая будет идти по всем тратам и добавлять их в ассоциативный массив, в котором в виде ключа будут даты: то есть все траты, сделанные в один и тот же день, попадут в один и тот же элемент.

Затем мы пройдёмся по всем дням и объединим их в месяцы:


И, наконец, после того, как у нас будут все месяцы с полным набором трат, мы можем вывести пользователю, сколько денег он потратил в каждом месяце и на что.

Давайте писать программу!
expenses_reader.rb :
require "rexml/document" # подключаем парсер require "date" # будем использовать операции с датами current_path = File.dirname(__FILE__) file_name = current_path + "/my_expenses.xml" # UNLESS в руби - противоположный по смыслу оператору IF # прерываем выполнение программы досрочно, если конечно файл не существует. abort "Извиняемся, хозяин, файлик my_expenses.xml не найден." unless File.exist?(file_name) file = File.new(file_name) # открыли файл doc = REXML::Document.new(file) # создаем новый документ REXML, построенный из открытого XML файла amount_by_day = Hash.new # пустой асс. массив, куда сложим все траты по дням # выбираем из элементов документа все тэги внутри # и в цикле проходимся по ним doc.elements.each("expenses/expense") do |item| # (Обратите внимание это локальная переменная объявленая в теле цикла, для каждой итерации # создается новая такая. За пределами цикла она не видна.) loss_sum = item.attributes["amount"].to_i # сколько потратили loss_date = Date.parse(item.attributes["date"]) # когда. Date.parse(. ) создает из строки объект Date # иницилизируем нулем значение хэша, если этой даты еще не было amount_by_day[loss_date] ||= 0 # в руби "a ||= b" эквивалентно "if a == nil a = b" # добавили трату за этот день amount_by_day[loss_date] += loss_sum end file.close # сделаем хэш, в который соберем сумму расходов за каждый месяц sum_by_month = Hash.new # в цикле по всем датам хэша amount_by_day накопим в хэше sum_by_month # значения потраченных сумм каждого дня amount_by_day.keys.sort.each do |key| # key.strftime("%B %Y") вернет одинаковую строку для всех дней одного месяца # поэтому можем использовать ее как уникальный для каждого месяца ключ sum_by_month[key.strftime("%B %Y")] ||= 0 sum_by_month[key.strftime("%B %Y")] += amount_by_day[key] # приплюсовываем к тому что было сумму следующего дня end # пришло время выводить статистику на экран # в цикле пройдемся по всем месяцам и начнем с первого current_month = amount_by_day.keys.sort[0].strftime("%B %Y") # выводим заголовок для первого месяца puts "------[ #, всего потрачено: # р. ]--------" # цикл по всем дням amount_by_day.keys.sort.each do |key| # если текущий день принадлежит уже другому месяцу. if key.strftime("%B %Y") != current_month # то значит мы перешли на новый месяц и теперь он станет текущим current_month = key.strftime("%B %Y") # выводим заголовок для нового текущего месяца puts "------[ #, всего потрачено: # р. ]--------" end # выводим расходы за конкретный день puts "\t#: # р." endНемного об HTML
HTML — грубо говоря, одна из разновидностей XML. Требования к разметке в некоторых версиях HTML, однако (а версий HTML много, сейчас, например, самая актуальная HTML5), могут существенно отличаться о того, что мы рассказали про XML.
Когда браузер заходит на какой-то сайт, он отправляет запрос и в качестве ответа получает в том числе текст в формате html. Браузер его обрабатывает и превращает в текст (также как Word превращает xml в те файлы, с которыми мы привыкли работать).

Давайте зайдём на сайт rubyrush.ru и посмотрим его html-разметку. Для этого нажмите на любой неактивный элемент на сайте правой кнопкой мыши и выберите пункт «Исходный код страницы», или просто нажмите Ctrl+U .

Те блоки гипертекста, которые вы видите, вам должны показаться знакомыми — тоже тэги, вложенные друг в друга, атрибуты и так далее. Нам это знание пригодится в последующих уроках, когда будем работать с сетью.
Итак, мы узнали о формате XML, научились читать данные из XML-файлов и узнали немного про HTML. На следующем уроке мы научимся писать свои XML файлы и сделаем так, чтобы нам не приходилось добавлять траты в файл expenses.xml руками.
Способы хранения данных в С++
На каникулы задали лабораторную работу (сделать программу, которая будет хранить метаданные файла, и текст содержащийся в нем, и различные функции для изменения данных), где одна из функций программ, это хранение данных, но обычное сохранение данных в txt файле не хочется делать. Как можно сохранять/хранить данные в другом формате?
Отслеживать
задан 4 янв 2019 в 17:46
Wart Vader Wart Vader
115 1 1 золотой знак 2 2 серебряных знака 16 16 бронзовых знаков
Гугл — c++ serialize habr.com/post/244963
4 янв 2019 в 18:23Можно использовать xml или json, если у вас данные, которые нельзя представить в текстовом формате (например стмвол ‘\0’ не может быть представлен в текстовом файле), то их следует перекодировать с помощью base64.
4 янв 2019 в 21:23
@AndrejLevkovitch, в текстовом файле могут быть представлены любые символы.
4 янв 2019 в 23:47
@Qwertiy я уверен, вы прекрастно поняли что имелось ввиду
5 янв 2019 в 5:55@AndrejLevkovitch, нет, я понял, что эта фраза может иметь более-менее правильную интерпретацию, да и то с натяжкой, а люди любят говорить всякую муть про текстовые файлы. И даже если я что-то понял, это не означает, что автор вопроса понял так же.
5 янв 2019 в 11:59
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Проще xml или json, как уже написали. Как вариант БД можно использовать sqlite. Очень проста в использовании и не требует дополнительной установки на компьютер. Достаточно положить sqlite-dll-win64-x64-3260000.zip библиотеки из архива рядом с базой. Удобный и бесплатный инструмент редактирования SQLiteManager.
Пример использования json могу дать такой(я использую Qt тут): сам json:
В функцию чтения передаётся путь до файла:
. QFileInfo info(QDir::currentPath()+"formatDate.json"); ReadJSON(QFileInfo info) .void MW::ReadJSON(QFileInfo info) < if (info.fileName()=="formatDate.json") < QString SettingsPath = info.absoluteFilePath(); QFile loadFile(SettingsPath); if (!loadFile.open(QIODevice::ReadOnly)) < QMessageBox::critical(this, tr("Ошибка"), tr("Нельзя открыть файл!")); return; >else < QByteArray SettingsData = loadFile.readAll(); QJsonDocument loadDoc(QJsonDocument::fromJson(SettingsData)); QJsonArray jsonArray = loadDoc["Format"].toArray(); foreach (const QJsonValue & value, jsonArray) < QJsonObject obj = value.toObject(); qDebug()> > >Функция записи файла:
void MW::SaveJSON() < QString PathToSettingsFiles = "formatDate.json"; QFileInfo fi(QDir::currentPath(), PathToSettingsFiles); QFile JsonFile(fi.absoluteFilePath()); JsonFile.open(QFile::WriteOnly); QJsonDocument JsonDoc; QJsonArray dateFormat_array; QString dateFormat_str("dateFormat"); QStringList DateList = < "MM.yyyy", "yyyy.MM", "dd.MM.yyyy" >; for (int x=0; x QJsonObject final_object; final_object.insert(QString("Format"), QJsonValue(dateFormat_array)); JsonDoc.setObject(final_object); JsonFile.write(JsonDoc.toJson()); return; >