Работа с файлами в Xamarin

Автор:

learn.microsoft.com

Работа с файлами в Xamarin.Forms может быть достигнута с помощью кода в библиотеке .NET Standard или с помощью встроенных ресурсов.

Обзор

Код Xamarin.Forms работает на нескольких платформах, каждая из которых имеет свою собственную файловую систему. Ранее это означало, что чтение и запись файлов проще всего было выполнять с помощью родных файловых API на каждой платформе. В качестве альтернативы встроенные ресурсы – более простое решение для распространения файлов данных вместе с приложением. Однако в .NET Standard 2.0 появилась возможность совместного использования кода доступа к файлам в библиотеках .NET Standard.

Сохранение и загрузка файлов

Классы System.IO можно использовать для доступа к файловой системе на каждой платформе. Класс File позволяет создавать, удалять и читать файлы, а класс Directory – создавать, удалять и перечислять содержимое каталогов. Вы также можете использовать подклассы Stream, которые могут обеспечить большую степень контроля над файловыми операциями (например, сжатие или поиск позиции в файле).

Текстовый файл может быть записан с помощью метода File.WriteAllText:

File.WriteAllText(fileName, text);

Текстовый файл можно прочитать с помощью метода File.ReadAllText:

string text = File.ReadAllText(fileName);

Кроме того, метод File.Exists определяет, существует ли указанный файл:

bool doesExist = File.Exists(fileName);

Путь к файлу на каждой платформе можно определить из библиотеки .NET Standard, используя значение перечисления Environment.SpecialFolder в качестве первого аргумента метода Environment.GetFolderPath. Затем это значение можно объединить с именем файла с помощью метода Path.Combine:

string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "temp.txt");

Эти операции демонстрируются в примере приложения, которое включает страницу, сохраняющую и загружающую текст:

Загрузка файлов, встроенных в качестве ресурсов

Чтобы встроить файл в сборку .NET Standard, создайте или добавьте файл и убедитесь, что Build Action: EmbeddedResource.

Visual Studio

Visual Studio for Mac

GetManifestResourceStream используется для доступа к встроенному файлу с помощью его идентификатора ресурса. По умолчанию идентификатор ресурса – это имя файла с префиксом пространства имен по умолчанию для проекта, в который он встроен – в данном случае сборка – WorkingWithFiles, а имя файла – LibTextResource.txt, поэтому идентификатор ресурса – WorkingWithFiles.LibTextResource.txt.

var assembly = IntrospectionExtensions.GetTypeInfo(typeof(LoadResourceText)).Assembly;
Stream stream = assembly.GetManifestResourceStream("WorkingWithFiles.LibTextResource.txt");
string text = "";
using (var reader = new System.IO.StreamReader (stream))
{ 
   text = reader.ReadToEnd ();
}

Переменная text может быть использована для отображения текста или другого использования его в коде. На этом снимке экрана из примера приложения показан текст, отображаемый в элементе управления Label.

Загрузка и десериализация XML не менее просты. Следующий код показывает, как XML-файл загружается и десериализуется из ресурса, а затем привязывается к ListView для отображения. XML-файл содержит массив объектов Monkey (класс определен в коде примера).

var assembly = IntrospectionExtensions.GetTypeInfo(typeof(LoadResourceText)).Assembly;
Stream stream = assembly.GetManifestResourceStream("WorkingWithFiles.LibXmlResource.xml");
List monkeys;
using (var reader = new System.IO.StreamReader (stream)) {
   var serializer = new XmlSerializer(typeof(List));
   monkeys = (List)serializer.Deserialize(reader);
}
var listView = new ListView ();
listView.ItemsSource = monkeys;


Встраивание в общие проекты

Общие проекты также могут содержать файлы в качестве встроенных ресурсов, однако, поскольку содержимое общего проекта компилируется в ссылающиеся проекты, префикс, используемый для идентификаторов ресурсов встроенных файлов, может меняться. Это означает, что идентификатор ресурса для каждого встроенного файла может быть разным для каждой платформы.

Существует два решения этой проблемы с общими проектами:

Синхронизировать проекты – отредактируйте свойства проекта для каждой платформы, чтобы использовать одно и то же имя сборки и пространство имен по умолчанию. Затем это значение может быть «жестко закодировано» в качестве префикса для идентификаторов встроенных ресурсов в общем проекте.

Директивы компилятора #if – Используйте директивы компилятора для установки правильного префикса идентификатора ресурса и используйте это значение для динамического построения правильного идентификатора ресурса.

Код, иллюстрирующий второй вариант, показан ниже. Директивы компилятора используются для выбора жестко закодированного префикса ресурса (который обычно совпадает с пространством имен по умолчанию для ссылающегося проекта). Затем переменная resourcePrefix используется для создания правильного идентификатора ресурса путем конкатенации с именем встроенного файла ресурса.

#if __IOS__
var resourcePrefix = "WorkingWithFiles.iOS.";
#endif
#if __ANDROID__
var resourcePrefix = "WorkingWithFiles.Droid.";
#endif
 
Debug.WriteLine("Using this resource prefix: " + resourcePrefix);
// note that the prefix includes the trailing period '.' that is required
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(SharedPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream
   (resourcePrefix + "SharedTextResource.txt");

Организация ресурсов

Приведенные выше примеры предполагают, что файл встроен в корень проекта библиотеки .NET Standard, в этом случае идентификатор ресурса имеет вид Namespace.Filename.Extension, например, WorkingWithFiles.LibTextResource.txt и WorkingWithFiles.iOS.SharedTextResource.txt.

Можно организовать встроенные ресурсы в папках. Когда встроенный ресурс помещается в папку, имя папки становится частью идентификатора ресурса (разделенное точками), так что формат идентификатора ресурса становится Namespace.Folder.Filename.Extension. Если поместить файлы, используемые в примере приложения, в папку MyFolder, то соответствующие идентификаторы ресурсов будут WorkingWithFiles.MyFolder.LibTextResource.txt и WorkingWithFiles.iOS.MyFolder.SharedTextResource.txt.

Отладка встроенных ресурсов

Поскольку иногда трудно понять, почему тот или иной ресурс не загружается, следующий отладочный код можно временно добавить в приложение, чтобы убедиться, что ресурсы правильно настроены. Он выведет все известные ресурсы, встроенные в данную сборку, на панель Errors, чтобы помочь отладить проблемы с загрузкой ресурсов.

using System.Reflection;
// ...
// use for debugging, not in released app code!
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(SharedPage)).Assembly;
foreach (var res in assembly.GetManifestResourceNames()) {
   System.Diagnostics.Debug.WriteLine("found resource: " + res);
}

Материалы по теме