Xamarin.Forms でのファイル処理
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);
各プラットフォームのファイル パスは、Environment.GetFolderPath
メソッドの最初の引数として Environment.SpecialFolder
列挙の値を使用することで、.NET Standard ライブラリから特定できます。 これを次に、Path.Combine
メソッドでファイル名と組み合わせることができます。
string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "temp.txt");
このような操作はサンプル アプリでデモとして示されています。これには、テキストを保存し、読み込むページが含まれています。
リソースとして埋め込まれたファイルを読み込む
.NET Standard アセンブリにファイルを埋め込むには、ファイルを作成するか追加し、[ビルド アクション] が [EmbeddedResource] になっていることを確認します。
GetManifestResourceStream
は、そのリソース ID を使用して埋め込みファイルにアクセスするために使用されます。 既定では、リソース ID は、リソースの埋め込み先のプロジェクトの既定の名前空間がプレフィックスとして付いたファイル名となります。この例では、アセンブリが WorkingWithFiles で、ファイル名が LibTextResource.txt であるため、リソース ID は 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 の読み込みと逆シリアル化は同じくらい簡単です。 次のコードは、リソースから読み込まれ、逆シリアル化され、表示のために ListView
にバインドされる XML ファイルを示します。 この XML ファイルには Monkey
オブジェクトの配列が含まれています (クラスはサンプル コードで定義されています)。
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(LoadResourceText)).Assembly;
Stream stream = assembly.GetManifestResourceStream("WorkingWithFiles.LibXmlResource.xml");
List<Monkey> monkeys;
using (var reader = new System.IO.StreamReader (stream)) {
var serializer = new XmlSerializer(typeof(List<Monkey>));
monkeys = (List<Monkey>)serializer.Deserialize(reader);
}
var listView = new ListView ();
listView.ItemsSource = monkeys;
共有プロジェクトに埋め込む
共有プロジェクトにも埋め込みリソースとしてファイルを含めることができます。ただし、共有プロジェクトの内容は参照元プロジェクトにコンパイルされるため、埋め込みファイル リソース ID に使用されるプレフィックスは変わることがあります。 つまり、埋め込みファイルごとのリソース ID はプラットフォームによって異なる場合があります。
共有プロジェクトのこの問題には 2 つの解決策があります。
- プロジェクトを同期する - 各プラットフォームのプロジェクト プロパティを編集し、同じアセンブリ名と既定の名前空間を使用します。 この値は共有プロジェクトの埋め込みリソース ID のプレフィックスとして "ハードコード" できます。
- #if コンパイラ ディレクティブ - コンパイラ ディレクティブを使用して正しいリソース ID プレフィックスを設定し、その値を使用して正しいリソース ID を動的に構築します。
2 つ目のオプションを示すコードを以下に示します。 コンパイラ ディレクティブを使用し、ハードコードされたリソース プレフィックス (通常、参照元プロジェクトの既定の名前空間と同じです) を選択します。 次に、resourcePrefix
変数を埋め込みリソース ファイル名と連結することで有効なリソース ID が作成されます。
#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 ライブラリ プロジェクトのルートにファイルが埋め込まれるものと想定されています。その場合、リソース ID の形式は Namespace.Filename.Extension で、WorkingWithFiles.LibTextResource.txt
や WorkingWithFiles.iOS.SharedTextResource.txt
のようになります。
埋め込みリソースはフォルダーで整理できます。 埋め込みリソースをフォルダーに入れると、フォルダー名がリソース ID の一部になります (ピリオドで区切られます)。そのため、リソース ID の形式は Namespace.Folder.Filename.Extension になります。 サンプル アプリで使用するファイルをフォルダー MyFolder に入れると、対応するリソース ID が WorkingWithFiles.MyFolder.LibTextResource.txt
と WorkingWithFiles.iOS.MyFolder.SharedTextResource.txt
になります。
埋め込みリソースのデバッグ
特定のリソースが読み込まれない理由がわからない場合があるため、リソースが正しく構成されていることを確認する目的で、次のデバッグ コードをアプリケーションに一時的に追加できます。 所与のアセンブリに埋め込まれている既知のリソースがすべて [エラー] パッドに出力されるので、リソース読み込み問題のデバッグに役立ちます。
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);
}
まとめ
この記事では、デバイスでテキストを保存し、読み込むことや埋め込みリソースを読み込むことなど、簡単なファイル操作をいくつか確認しました。 .NET Standard 2.0 の場合、.NET Standard ライブラリでファイル アクセス コードを共有できます。