Windows Runtime APIはファイルの扱いが独特だ。そこで、本稿では、このAPIを使ってファイルをコピー/移動/削除する方法を解説する。
powered by Insider.NET
ファイルを他のフォルダーへ移動/コピーする、あるいは削除する。基本的なことではあるが、デスクトップアプリ開発やASP.NETのWeb開発からWindowsランタイムアプリ開発に移ってきた人にとっては、どうすればよいのか分かりにくいかもしれない。そこで本稿では、Windows 8.1とWindows Phone 8.1用のユニバーサルWindowsアプリ、およびWindows 10用のユニバーサルWindowsアプリで共通に使える方法を解説する。なお、本稿のサンプルは「Windows Store app samples:MetroTips #106」からダウンロードできる。
Windows 8.1とWindows Phone 8.1用のユニバーサルWindowsアプリを開発するには、以下の開発環境が必要である。本稿では、無償のVisual Studio Community 2013 with Update 4を使っている。
*1 SLAT対応ハードウエアは、Windows Phone 8.1エミュレーターの実行に必要だ。ただし未対応でも、ソースコードのビルドと実機でのデバッグは可能だ。SLAT対応のチェック方法はMSDNブログの「Windows Phone SDK 8.0 ダウンロードポイント と Second Level Address Translation (SLAT) 対応PCかどうかを判定する方法」を参照。なお、SLAT対応ハードウエアであっても、VM上ではエミュレーターが動作しないことがあるのでご注意願いたい。
*2 事前には「Windows 8.1 Update 1」と呼ばれていたアップデート。スタート画面の右上に検索ボタンが(環境によっては電源ボタンも)表示されるようになるので、適用済みかどうかは簡単に見分けられる。ちなみに公式呼称は「the Windows RT 8.1, Windows 8.1, and Windows Server 2012 R2 update that is dated April, 2014」というようである。
*3 Windows Phone 8.1エミュレーターを使用しないのであれば、32bit版のWindows 8.1でもよい。
*4 マイクロソフトのダウンロードページから誰でも入手できる(このURLはUpdate 4のもの)。
*5 本稿に掲載したコードを試すだけなら、無償のExpressエディションやCommunityエディションで構わない。Visual Studio Express 2013 with Update 4 for Windows(製品版)はマイクロソフトのページから無償で入手できる。Expressエディションはターゲットプラットフォームごとに製品が分かれていて紛らわしいが、Windowsランタイムアプリの開発には「for Windows」を使う(「for Windows Desktop」はデスクトップで動作するアプリ用)。また、2014年11月12日(米国時間)に新しくリリースされたVisual Studio Community 2013 with Update 4(製品版)もマイクロソフトのページから無償で入手できる。Communityエディションは本稿執筆時点では英語版だけなので、同じ場所にあるVisual Studio 2013 Language Packの日本語版を追加インストールし、[オプション]ダイアログで言語を切り替える必要がある。
.NET Frameworkで開発してきた人は、ファイルの移動やコピーというとSystem.IO名前空間のFileクラスなどを思い浮かべるだろう。しかし、WindowsランタイムではWindows.Storage名前空間のクラスを主に利用する。System.IO名前空間は使えなくもないが、かえって面倒になる。
ファイルの移動/コピー/削除には、以下に挙げるクラスをよく利用する。
なお、本稿で紹介するコードはWindows Phone 8.1でも動作するものだが、StorageFileクラス/StorageFolderクラスの中にはWindows Phone 8.1でサポートされていないメソッドなどもあるので注意してほしい。
移動/コピー/削除の対象とするファイルは、上述したStorageFileオブジェクトとして扱う。ところが、Windowsランタイムアプリでは、ファイルのフルパスを使ってファイルのオブジェクトを得ることはできないのだ。本稿では、StorageFileオブジェクトは取得できているものとして話を進めるが、簡単に紹介しておこう。StorageFileオブジェクトを取得するには、次のような方法を用いる。
また、処理対象のフォルダーはStorageFolderオブジェクトとして扱うのだが、これも同様にして取得できる(ピッカーにはFolderPickerクラスも用意されている)。
StorageFileクラスのCopyAsyncメソッドを使えばよい。
例えば、アプリのローカルフォルダーへコピーするコードは次のようになる。
// コピー元のファイル(何らかの手段で取得したStorageFileオブジェクト)
StorageFile file = ……省略……
// コピー先:アプリのローカルフォルダー
StorageFolder targetFolder = ApplicationData.Current.LocalFolder;
// コピーを実行する
var destFile = await file.CopyAsync(targetFolder);
' コピー元のファイル(何らかの手段で取得したStorageFileオブジェクト)
Dim file As StorageFile = ……省略……
' コピー先:アプリのローカルフォルダー
Dim targetFolder As StorageFolder = ApplicationData.Current.LocalFolder
' コピーを実行する
Dim destFile = Await file.CopyAsync(targetFolder)
ただし、上のコードでは、コピー先に同じ名前のファイルがすでに存在していると、例外が発生する。そのようなときにどうするかを、NameCollisionOption列挙型を引数に与えて指定できる。例えば、コピー先に同じ名前のファイルがあったときに上書きするには、次のコードのようにする。
// コピー元のファイル(何らかの手段で取得したStorageFileオブジェクト)
StorageFile file = ……省略……
// コピー先:アプリのローカルフォルダー
StorageFolder targetFolder = ApplicationData.Current.LocalFolder;
// コピーを実行する
var destFile = await file.CopyAsync(targetFolder, file.Name,
NameCollisionOption.ReplaceExisting);
' コピー元のファイル(何らかの手段で取得したStorageFileオブジェクト)
Dim file As StorageFile = ……省略……
' コピー先:アプリのローカルフォルダー
Dim targetFolder As StorageFolder = ApplicationData.Current.LocalFolder
' コピーを実行する
Dim destFile = Await file.CopyAsync(targetFolder, file.Name,
NameCollisionOption.ReplaceExisting)
StorageFileクラスのMoveAsyncメソッドを使えばよい。
使い方は、上のCopyAsyncメソッドとほぼ同じだが、返値を持たないところが異なる。ファイルのコピーでは新しいファイルが作られるので、それにアクセスするには新しいStorageFileオブジェクトが必要だった。ファイルの移動では、「元のファイルがそのまま場所を変えただけ」だと考えるので、元のStorageFileオブジェクトで引き続きアクセスできるのである。
例えば、アプリのローカルフォルダーへ移動するコードは次のようになる。
// 移動元のファイル(何らかの手段で取得したStorageFileオブジェクト)
StorageFile file = ……省略……
// 移動先:アプリのローカルフォルダー
StorageFolder targetFolder = ApplicationData.Current.LocalFolder;
// ファイルを移動する
await file.MoveAsync(targetFolder);
' 移動元のファイル(何らかの手段で取得したStorageFileオブジェクト)
Dim file As StorageFile = ……省略……
' 移動先:アプリのローカルフォルダー
Dim targetFolder As StorageFolder = ApplicationData.Current.LocalFolder
' ファイルを移動する
Await file.MoveAsync(targetFolder)
上のコードでは、移動先に同じ名前のファイルがすでに存在していると、コピーと同様に例外が発生する。その場合に上書きするのであれば、やはりコピーと同様にNameCollisionOption.ReplaceExistingオプションを指定すればよい。ファイル名が衝突したときに自動的に別の名前にして移動するには、次のコードのようにする。
// 移動元のファイル(何らかの手段で取得したStorageFileオブジェクト)
StorageFile file = ……省略……
// 例として、このStorageFileオブジェクト(=file変数)のパス(=Pathプロパティ)が
// 「……省略……\TempState\sample.txt」だったとする
// 移動先:アプリのローカルフォルダー
StorageFolder targetFolder = ApplicationData.Current.LocalFolder;
// ファイルを移動する
await file.MoveAsync(targetFolder, file.Name, NameCollisionOption.GenerateUniqueName);
// 移動先のフォルダーにすでに同名のファイルが存在していた場合には、
// StorageFileオブジェクト(=file変数)のパスが、移動後に例えば次のように変わっている
// Windows 8.1:……省略……\LocalState\sample - コピー.txt
// Windows Phone 8.1:……省略……\LocalState\sample (1).txt
' 移動元のファイル(何らかの手段で取得したStorageFileオブジェクト)
Dim file As StorageFile = ……省略……
' 例として、このStorageFileオブジェクト(=file変数)のパス(=Pathプロパティ)が
' 「……省略……\TempState\sample.txt」だったとする
' 移動先:アプリのローカルフォルダー
Dim targetFolder As StorageFolder = ApplicationData.Current.LocalFolder
' ファイルを移動する
Await file.MoveAsync(targetFolder, file.Name, NameCollisionOption.GenerateUniqueName)
' 移動先のフォルダーにすでに同名のファイルが存在していた場合には、
' StorageFileオブジェクト(=file変数)のパスが、移動後に例えば次のように変わっている
' Windows 8.1:……省略……\LocalState\sample - コピー.txt
' Windows Phone 8.1:……省略……\LocalState\sample (1).txt
StorageFileクラスのDeleteAsyncメソッドを使えばよい(次のコード)。
// 削除したいファイル(何らかの手段で取得したStorageFileオブジェクト)
StorageFile file = ……省略……
// ファイルを削除する
await file.DeleteAsync();
' 削除したいファイル(何らかの手段で取得したStorageFileオブジェクト)
Dim file As StorageFile = ……省略……
' ファイルを削除する
Await file.DeleteAsync()
上のコードでは、ファイルが「ごみ箱」に送られるだけで完全には削除されないことがある。アプリのローカルデータ記憶域にあるファイル(=ApplicationDataクラスを利用してアクセスするファイル)とネットワークドライブにあるファイルは、完全に削除される。ローカルディスクでそれ以外の場所にあるファイルは「ごみ箱」に送られるのだ。
常に完全に削除したい場合は、次のコードのようにしてStorageDeleteOption列挙型のPermanentDeleteメンバーを引数に指定すればよい。
// 削除したいファイル(何らかの手段で取得したStorageFileオブジェクト)
StorageFile file = ……省略……
// ファイルを常に完全に削除する
await file.DeleteAsync(StorageDeleteOption.PermanentDelete);
' 削除したいファイル(何らかの手段で取得したStorageFileオブジェクト)
Dim file As StorageFile = ……省略……
' ファイルを常に完全に削除する
Await file.DeleteAsync(StorageDeleteOption.PermanentDelete)
ファイルの移動/コピー/削除は、Windows.Storage名前空間のStorageFileクラスを使うと簡単だ。ファイルを別のフォルダーへ移動したときにStorageFileオブジェクトが(消滅/生成せずに)変化するという挙動は、慣れないと戸惑うかもしれない。
Microsoft Virtual Academy(MVA)では、マイクロソフトのトレーニングコースが無償で受講できる。多数あるコースの中から、これからユニバーサルWindowsアプリを開発してみたいという人にぴったりのものを紹介しよう。
Copyright© Digital Advantage Corp. All Rights Reserved.