読者です 読者をやめる 読者になる 読者になる

がりらぼ

WindowsRuntimeの応援ブログ

WindowsPhone8.1でデータを保存する6つの方法

完全に釣りタイトルです。

Office365毎日更新ブログで有名な@kazuakixさんのブログで興味深い記事がありました。

Windows Phone 8.1 でアプリの設定を保存する - kazuakix の日記

そうです、WindowsPhone8.1からWindowsRuntimeAPIに統合されたのでIsolatedStorageはAplicationDataに置き換えられました。

こうすることでWindowsストアアプリとの差がほとんどなくなりました。 (ちなみにIsolatedStorageはWindowsPhone8.1ではつかえなくなってました)

汎用的でレベルの高いデータ保存はつもりんやむっつ氏が書いてくれてるので僕は初歩的なところをまとめていきたいです。

WinRTでアプリの設定を保存する - tmytのらくがき

gist:5fdf58f42800a3b620ae

設定データとファイルデータ

まず、抑えて置かなければいけない概念として、WindowsRuntimeでは設定データとファイルデータの2つのデータ保存方法があります。

単純な設定データなどは設定データとして~Settingに保存します。 大きいデータやファイル単位で保存したいデータは~Folder内にファイルを作って保存します。

設定データは、ApplicationDataContainerクラスで作られていて、キーそれに対応する値のセットでつくられます。

ファイルデータは、StorageFolderクラスとして保存するフォルダーを取得することができるのでそこにファイルとして書き込みます。

具体的には、ApplicationDataクラスの中に、

設定データ(ApplicationDataContainer型)
  • LocalSetting - ローカルの設定データ
  • RoamingSetting - ローミング設定データ
ファイルデータを入れるフォルダー(StorageFolder型)
  • LocalFolder - ローカルファイルフォルダー
  • RoamingFolder - ローミングファイルフォルダー
  • TemporaryFolder - 一時的なデータを保存するファイルフォルダー
  • LocalCacheFolder - 一時データ?

の6つのプロパティがあり、そこにデータを入れることになります。

f:id:garicchi:20140714130709p:plain

LocalCacheFolderについては、いまだMSDNにも情報がなく、おそらくはローカルのキャッシュデータ保存用フォルダだとは思いますが、一時データ保存用フォルダということにしときます。

ローカルデータとローミングデータ

さらに、WindowsRuntimeでは複数のデバイス間でデータを同期できるようにデータローミングという概念を採用しています。 Roamingがつく設定やフォルダーにデータを入れると、データはOneDriveで同期され、別のデバイスでも同じデータを扱うことができます。 ユニバーサルアプリの場合、「アプリをストアに関連付ける」をした後、WindowsアプリとWindowsPhoneアプリ間でデータがローミングされます。

f:id:garicchi:20140714130531p:plain

ローミングデータは、データサイズに上限があり、それ以上のデータを入れると同期されません。

データサイズの取得方法はRoamingStorageQuotaで取得できます。

ulong size=ApplicationData.Current.RoamingStorageQuota;

では、具体的なデータ保存、復元方法を見て行きましょう。

ローカル設定データ

ローカル設定データは、LocalSettingというコンテナーにキーと値をセットにしてデータを保存します。

public void SaveTextToLocalSetting(string key,string value)
{
    ApplicationDataContainer container = ApplicationData.Current.LocalSettings;
    container.Values[key] = value;
}

データを復元するときは、ContainsKeyを使ってキーがすでにあるかどうかを判定しましょう。

public string LoadTextFromLocalSetting(string key)
{
    ApplicationDataContainer container = ApplicationData.Current.LocalSettings;
    if (container.Values.ContainsKey(key))
    {
        return container.Values[key].ToString();
    }
    else
    {
        return null;
    }
}

ローミング設定データ

データが同期される設定データは、RoamingSettingに保存します。 保存方法はLocalSettingと同じですが、この設定データは異なるデバイス間の同じアプリで同期されます。

public void SaveTextToRoamingSetting(string key, string value)
{
    ApplicationDataContainer container = ApplicationData.Current.RoamingSettings;
    container.Values[key] = value;
}

データ復元

public string LoadTextFromRoamingSetting(string key)
{

    ApplicationDataContainer container = ApplicationData.Current.RoamingSettings;
    if (container.Values.ContainsKey(key))
    {
        return container.Values[key].ToString();
    }
    else
    {
        return null;
    }
}

ローカルファイルデータ

大きいファイルを保存する場合は、LocalFolderにStorageFolderを作って保存しましょう。

StorageFildeのCreateFileAsyncメソッドを使ってファイルを作ります。

今回はFileIOクラスのWriteTextAsyncでテキストデータを書き込みます。

public async Task SaveTextFileToLocalFolderAsync(string fileName, string value)
{
    StorageFolder folder = ApplicationData.Current.LocalFolder;
    StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
    await FileIO.WriteTextAsync(file,value);
    
}

もし、byteデータを書き込みたい場合はこちらを御覧ください

byteデータを書き込むには | garicchi.com

byteデータを読み込むには | garicchi.com

データ復元は、GetFileAsyncでデータを取得します。

その前に、GetFilesAsyncでファイル一覧を取得し、データが保存されているかどうかを判定します。

public async Task<string> LoadTextFileFromLocalFolderAsync(string fileName)
{
    StorageFolder folder = ApplicationData.Current.LocalFolder;
    if ((await folder.GetFilesAsync()).Where(q => q.Name == fileName).Any())
    {
        StorageFile file = await folder.GetFileAsync(fileName);
        return await FileIO.ReadTextAsync(file);
    }
    else
    {
        return null;
    }
}

ローミングファイルデータ

ファイルもデータローミングすることができます。

RoamingFolderに先ほどと同じようにファイルをつくり、書き込みます。

public async Task SaveTextFileToRoamingFolderAsync(string fileName, string value)
{
    StorageFolder folder = ApplicationData.Current.RoamingFolder;
    StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
    await FileIO.WriteTextAsync(file, value);

}

データ復元

public async Task<string> LoadTextFileFromRoamingFolderAsync(string fileName)
{
    StorageFolder folder = ApplicationData.Current.RoamingFolder;
    if ((await folder.GetFilesAsync()).Where(q => q.Name == fileName).Any())
    {
        StorageFile file = await folder.GetFileAsync(fileName);
        return await FileIO.ReadTextAsync(file);
    }
    else
    {
        return null;
    }
}

一時データ

一時データは、TemporaryFolderに保存します。

このフォルダ内のデータは、一時データとはキャッシュのようなもので、システムによってシステムメンテナンスや任意の時点で削除されてしまうので、データの長期保存を保証しません。

データ保存

public async Task SaveTextFileToTemporaryFolderAsync(string fileName, string value)
{
    StorageFolder folder = ApplicationData.Current.TemporaryFolder;
    StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
    await FileIO.WriteTextAsync(file, value);

}

データ復元

public async Task<string> LoadTextFileFromTemporaryFolderAsync(string fileName)
{
    StorageFolder folder = ApplicationData.Current.TemporaryFolder;
    if ((await folder.GetFilesAsync()).Where(q => q.Name == fileName).Any())
    {
        StorageFile file = await folder.GetFileAsync(fileName);
        return await FileIO.ReadTextAsync(file);
    }
    else
    {
        return null;
    }
}

ローカルキャッシュ

ローカルキャッシュはLocalCacheFolderに保存します。 ローカルキャッシュフォルダーの定義としては、 「バックアップと復元の対象にならないファイルの保存先にできるローカルのアプリデータストア内のフォルダーを取得」 とあるのですが、アプリを一度終了してみても、データは復元できたのでTemporaryフォルダーと同じ扱いと考えました。 こちらも長期保存は保証していません。

データ保存

public async Task SaveTextFileToLocalCacheFolderAsync(string fileName, string value)
{
    StorageFolder folder = ApplicationData.Current.LocalCacheFolder;
    StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
    await FileIO.WriteTextAsync(file, value);

}

データ復元

public async Task<string> LoadTextFileFromLocalCacheFolderAsync(string fileName)
{
    StorageFolder folder = ApplicationData.Current.LocalCacheFolder;
    if ((await folder.GetFilesAsync()).Where(q => q.Name == fileName).Any())
    {
        StorageFile file = await folder.GetFileAsync(fileName);
        return await FileIO.ReadTextAsync(file);
    }
    else
    {
        return null;
    }
}

リンク

アプリの設定を保存するには | garicchi.com

アプリの同期設定を保存するには | garicchi.com

アプリの設定データに階層構造を持ったデータを保存するには-ApplicationDataCompositeValue編 | garicchi.com

アプリの設定データに階層構造を持ったデータを保存するには-複数コンテナー編 | garicchi.com

アプリの設定データに階層構造を持ったデータを保存するには-JSONシリアライズ編 | garicchi.com

テキストファイルを書き込むには | garicchi.com

テキストファイルを読み込むには | garicchi.com

byteデータを書き込むには | garicchi.com

byteデータを読み込むには | garicchi.com

アプリの同期ファイルを保存するには | garicchi.com

アプリの一時データを保存するには | garicchi.com

StorageFileをアプリデータとして取り込むには | garicchi.com