Adobe AIRで作るデスクトップアプリケーション

第7回ファイルシステムAPI(その1)

ファイルやディレクトリへのアクセス

ブラウザ上で実行されるウェブアプリケーションがローカルファイルへのアクセスを制限されているのに対し、AIRアプリケーションは比較的自由にローカルファイルへアクセスできます。しかもプラットフォーム間の差異はAIR側で吸収してくれるので、デベロッパーが意識してコードを書き分ける必要もありません。

例として、デスクトップディレクトリにアクセスしてみましょう。

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="test()">
	<mx:Script>
		<![CDATA[
			import flash.filesystem.File;
			private function test():void {
				var dir:File = File.desktopDirectory;
				trace(dir.nativePath);
			}
		]]>
	</mx:Script>
</mx:WindowedApplication>
出力結果
Macintoshの場合:/Users/ユーザ名/Desktop
Windowsの場合:C:\Documents and Settings\ユーザ名\デスクトップ

このように1つのコードで複数のプラットフォームに対応できるわけです。

ファイルやディレクトリの参照にはFileオブジェクトを使います。Fileクラスには、よく使う一般的なディレクトリが以下の静的プロパティとして定義されています。アプリケーションの設定ファイル等、ユーザの目に触れる必要のないデータはapplicationStorageDirectoryを使うとよいでしょう。

applicationResourceDirectory:Fileアプリケーションのリソースがインストールされているディレクトリ
applicationStorageDirectory:Fileアプリケーション毎に割り当てられる保存用ディレクトリ
desktopDirectory:Fileユーザのデスクトップディレクトリ
documentsDirectory:Fileユーザのドキュメントディレクトリ
userDirectory:Fileユーザのホームディレクトリ

nativePathプロパティは、Fileオブジェクトが参照しているファイルやディレクトリのフルパスです。前記の出力結果の通り、パスの表記はプラットフォームに依存したものが使われます。nativePathプロパティに直接値を代入してパスを指定することもできます。例えば、Windowsのマイ ドキュメント内にあるsample.txtを指定するには、次のように記述できます。

var file:File = new File();
file.nativePath = "C:\Documents and Settings\ユーザ名\My Documents\sample.txt";

※WindowsではnativePathプロパティのパスデリミタとして"\"の代わりに"/"を使うこともできます。Macintoshでは"/"のみです。

しかし、パスの先頭にはプロパティとして用意されたディレクトリを利用し、なるべく汎用性のあるコードにしたほうがよいでしょう。ディレクトリ下のパスは、resolve()メソッドを使って相対的に指定できます。

var dir:File = File.documentsDirectory;
var file:File = dir.resolve("sample.txt");

親ディレクトリは、resolve()メソッドで".."を指定するかparentプロパティを使って参照できます。次の2つは同じディレクトリになります。

var dir1:File = File.userDirectory.resolve("..");
var dir2:File = File.userDirectory.parent;

nativePathプロパティ対して、プラットフォームに依存しない形式のurlプロパティもあります。urlプロパティの場合は、"file://"等のURLスキームが使われます。

var dir:File = File.userDirectory;
trace(dir.url);
出力結果
Macintoshの場合:file:///Users/ユーザ名
Windowsの場合:file:///C:/Documents%20and%20Settings/ユーザ名

URLスキームは、標準的なfile以外に次のものがあります。

app-resourceアプリケーションのリソースがインストールされているディレクトリを表す
app-storageアプリケーション毎に割り当てられる保存用ディレクトリを表す

applicationResourceDirectoryプロパティやapplicationStorageDirectoryプロパティの代わりにこれらを使ってアプリケーション固有のディレクトリにアクセスできます。

var file:File = new File();
file.url = "app-storage:/config/prefs.xml";

ファイルやディレクトリの情報を調べる

Fileオブジェクトが参照しているファイルやディレクトリに関する情報は、Fileクラスのプロパティで調べられます。以下が代表的なものです。

name:String名前
size:Numberサイズ(byte)
extension:String拡張子
creationDate:Date 作成日時
modificationDate:Date最終更新日時
isHidden:Boolean不可視かどうか
isDirectory:Booleanディレクトリかどうか
icon:Icon関連付けされているアイコン
exists:Boolean存在するかどうか

iconプロパティは少し特殊なので説明しておきます。これはファイルアイコンやフォルダアイコンをBitmapDataオブジェクトで取得できるプロパティです。値となるIconオブジェクトは、アイコンデータに含まれる複数のイメージをbitmapsというプロパティに配列として保持しています。次のコードではAIRファイルのアイコンをステージに並べています。

var file:File = File.desktopDirectory.resolve("sample.air");
var images:Array = file.icon.bitmaps;
var xpos:uint = 0;
for (var i:uint = 0; i < images.length; i++) {
	var bmp:Bitmap = new Bitmap(images[i]);
	bmp.x = xpos;
	xpos += bmp.width;
	window.stage.addChild(bmp);
}
ファイルやフォルダのアイコンを取得できる
ファイルやフォルダのアイコンを取得できる

同期メソッドと非同期メソッド

Fileオブジェクトにファイルやディレクトリを指定したら、それに対してコピーや移動、削除といった操作ができます。これらの操作を行うメソッドの多くに、同期バージョンと非同期バージョンがあります。例えば、同期メソッドのcopyTo()と非同期メソッドのcopyToAsync()は、どちらもファイルやディレクトリをコピーするためのメソッドです。

同期メソッドの場合、ファイル操作が完了してから次の処理に移ります。処理の流れが分かりやすく、コードがシンプルになるのが利点ですが、ファイル操作に時間がかかると他の処理が止まってしまいます。したがって、ファイルサイズが比較的小さく、処理がすぐ終わる場合に向いています。

非同期メソッドの場合、ファイル操作を行いながらバックグラウンドで他の処理も進行するので、プログレス表示なども行えます。ファイルサイズが大きい場合や不明な場合は非同期メソッドを使ったほうがよいでしょう。ファイル操作の完了やエラーはイベントによって通知されます。

ファイルやディレクトリのコピー、移動

ファイルやディレクトリのコピーや移動を行うには、Fileクラスの以下のメソッドを使います。

同期メソッド非同期メソッド
ファイルやディレクトリをコピーcopyTo()copyToAsync()
ファイルやディレクトリを移動moveTo()moveToAsync()

コピーと移動はメソッド名が違うだけで、使い方は同じです。まずは同期メソッドから見ていきましょう。次のコードはcopyTo()メソッドを使ってファイルをコピーする例です。

var file1:File = File.documentsDirectory.resolve("sample.txt");
var file2:File = File.desktopDirectory.resolve("sample.txt");
try {
	file1.copyTo(file2, true);
} catch (error:IOError) {
	trace(error.message);
}

このように、コピー元のFileオブジェクトに対してcopyTo()を実行し、コピー先を示すFileオブジェクトを引数として渡します。copyTo()の2番目の引数は上書きフラグです。trueを指定すると既存のファイルに上書きコピーします。上書きフラグがfalse(デフォルト値)の場合にコピー先ファイルが存在すると、IOErrorがスローされます。コピー元のファイルが無い場合や、使用中のファイルに上書きしようとした場合などもエラーとなります。

次に非同期メソッドを使った方法を見てみましょう。次のコードはcopyToAsync()メソッドを使ってファイルをコピーする例です。メソッドの使い方はcopyTo()と変わりませんが、イベントリスナーを登録してコピーの完了通知やエラー通知を受け取る点が異なります。

var file1:File = File.documentsDirectory.resolve("sample.txt");
var file2:File = File.desktopDirectory.resolve("sample.txt");
file1.addEventListener(Event.COMPLETE, onFileCopyComplete);
file1.addEventListener(IOErrorEvent.IO_ERROR, onFileCopyError);
file1.copyToAsync(file2, true);

private function onFileCopyComplete(event:Event):void {
	trace("コピー完了");
}
private function onFileCopyError(event:IOErrorEvent):void {
	trace("I/Oエラー");
}

ファイルやディレクトリの作成

ファイルやディレクトリの作成を行うには、Fileクラスの以下のメソッドを使います。

ディレクトリを作成createDirectory()
一時ファイルを作成createTempFile()
一時ディレクトリを作成createTempDirectory()

作成したいディレクトリをFileオブジェクトに指定し、createDirectory()を実行するとディレクトリが作成されます。指定のディレクトリが既に存在する場合は何もしません。

var dir:File = File.desktopDirectory.resolve("Sounds");
dir.createDirectory();

createTempFile()とcreateTempDirectory()は、一時ファイルや一時ディレクトリを作成しFileオブジェクトとして返します。これらは静的メソッドです。実行するたびに新規のユニークなものを作成します。

var tempFile:File = File.createTempFile();
var tempDir:File = File.createTempDirectory();

なお、一時ファイルや一時ディレクトリはAIRアプリケーションを終了しても自動的には削除されません。不要になったら明示的に削除する必要があります。

ファイルやディレクトリの削除

ファイルやディレクトリの削除を行うには、Fileクラスの以下のメソッドを使います。ゴミ箱への移動に関しては、実際の削除までは行われません。

同期メソッド非同期メソッド
ファイルを削除deleteFile()deleteFileAsync()
ディレクトリを削除deleteDirectory()deleteDirectoryAsync()
ファイルやディレクトリをゴミ箱へ移動moveToTrash()moveToTrashAsync()

メソッドの使い方はこれまで説明してきたものと同様で、対象となるFileオブジェクトに対して呼び出します。いずれも指定のパスが無かったり使用中で削除できない場合はエラーとなります。

deleteDirectory()とdeleteDirectoryAsync()は引数を1つ取ります。指定のディレクトリにファイルやサブディレクトリが含まれていた場合に削除するかどうかを指定するフラグです。false(デフォルト値)の場合、空でないディレクトリを削除しようとするとエラーとなります。

ディレクトリの内容を調べる

ディレクトリ内にどのようなファイルやフォルダがあるか調べるには、Fileクラスの次のメソッドを使います。

同期メソッド非同期メソッド
ディレクトリ内の一覧を取得listDirectory()listDirectoryAsync()

これらのメソッドは、指定のディレクトリ内にあるファイルやディレクトリを配列で返します。配列の各要素はFileオブジェクトです。なお、配列に含まれるのは指定のディレクトリの直下にあるものだけで、サブディレクトリの内容は列挙されません。次のコードはデスクトップディレクトリの内容を出力します。

var dir:File = File.desktopDirectory;
var files:Array = dir.listDirectory();
for (var i:uint = 0; i < files.length; i++) {
	trace(files[i].nativePath);
}

おすすめ記事

記事・ニュース一覧