Palm Programmer's Laboratory
Palm OS Programmer's Companion Volume I/7-8
7-8 ファイルの操作
デスクトップアプリケーションで行なう見慣れたファイル操作は全て、VFSマネージャによってサポートされています。それらの操作はこのページの“共通的な操作”にリストされています。さらに、Palmデータベース(.pdb)やPalmリソースデータベース(.prc)のようなファイルに対する操作を簡単にするための関数のセットが含まれています。これらの関数については、“Palmデータベースの操作”で説明しています。
共通的な操作
VFSマネージャはデスクトップや大きなコンピュータシステムに見られる標準的なファイル操作を全て提供しています。これらの関数はおおむね予想どおりに機能するため、使用法の詳細については割愛します。引数や復帰値、および副作用については、Palm OS Programmer's API Reference の各関数の説明を参照して下さい。
これらの関数のうち、いくつかはファイルとディレクトリの両方に使用することができますが、その他はファイルのみに対して機能します。
表 7.2 共通ファイル操作
関数名 | 説明 |
---|---|
VFSFileOpen | ボリューム参照番号とファイルパスを指定し、ファイルを開きます。 |
VFSFileClose | 開いているファイルを閉じます。 |
VFSFileRead | ファイルからダイナミックヒープやその他の書込み可能メモリにデータを読み込みます。 |
VFSFileReadData | ファイルからストレージヒープ内のメモリチャンクにデータを読み込みます。 |
VFSFileWrite | 開いているファイルにデータを書込みます。 |
VFSFileSeek | 開いているファイルに対して読み書きを行なう位置を設定します。 |
VFSFileTell | 開いているファイルのファイルポインタの現在位置を取得します。 |
VFSFileEOF | 開いているファイルの EOF ステータスを取得します。 |
VFSFileCreate | ボリューム参照番号とファイルパスを指定し、ファイルを作成します。 |
VFSFileDelete | 閉じているファイルを削除します。 |
VFSFileRename | 閉じているファイルの名前を変更します。 |
VFSFileSize | 開いているファイルのサイズを取得します。 |
VFSFileResize | 開いているファイルのサイズを変更します。 |
VFSFileGetAttributes | 開いているファイルの属性を取得します。これには、隠しファイル、読取り専用、システム、およびアーカイブの各ビットが含まれます。この属性フィールドを構成するビットの詳細については Palm OS Programmer's API Reference の“ファイルとディレクトリの属性”を参照して下さい。 |
VFSFileSetAttributes | 開いているファイルの属性を設定します。これには、隠しファイル、読取り専用、システム、およびアーカイブの各ビットが含まれます。 |
VFSFileGetDate | 開いているファイルの作成日付、変更日付、および最終アクセス日付を取得します。 |
VFSFileSetDate | 開いているファイルの作成日付、変更日付、および最終アクセス日付を設定します。 |
ファイルを開くと、そのファイルは FileRef という一意な参照番号で識別されます。開かれたファイルを使用する関数はファイル参照番号を要求します。その他の、VFSFileOpen のような関数は、ボリューム参照とそのボリューム内でファイルを識別するパスを要求します。全てのパスはボリューム相対であり、ボリューム内で絶対であることに注意して下さい。VFSマネージャは現在の“作業ディレクトリ”という概念を持ちません。そのため、相対パス名はサポートされません。ディレクトリセパレータ文字はスラッシュ“/”です。ボリュームのルートディレクトリはパス名“/”で示されます。
ファイルの命名
異なるファイルシステムはファイル名やパス名を異なる最大長でサポートします。ファイルシステムライブラリは与えられたパス名の正当性を検証する責任を持ち、不正なパスであればエラーを返します。アプリケーション開発者の立場からは、ファイル名は最大で 255文字であり、あらゆる文字セットの空白文字や小文字を含む全ての通常文字を使用することができます。また、以下の特殊文字を含むこともできます。
$ % ' - _ @ ~ ‘ ! ( ) ^ # & + , ; = [ ]
ファイルシステムライブラリは、ファイル名やパス名をベースになるファイルシステムにとって正当なフォーマットに変換する責任があります。例えば、8.3 命名規則を使用して長いファイル名を変換する場合、以下のガイドラインが適用されます。
- ファイル名はスペースでない有効な最初の6文字から作成されます。ただし、使用されるのは最後に出現するピリオドよりも手前の文字だけです。有効な文字は A-Z, 0-9, $, %, ‘, -, _, @, ~, ‘, !, (, ), ^, #, および & だけです。
- 拡張子は最後に出現するピリオドから3文字が使用されます。
- 6 文字の名前の後ろには、それが短縮されたファイル名の1つ目であれば“~1”が付加されます。後続する同一の短縮名に対しては、2番目であれば“~2”のように一意な番号が付加されます。
標準の VFAT ファイルシステムライブラリは、長いファイル名からFAT準拠の名前を生成する上記のルールを使用した拡張をサポートする全てのPalmハンドヘルドで提供されます。
Palmデータベースの操作
拡張カードは、時として .prc および .pdb フォーマットの Palmアプリケーションとデータを保持するために使われます。セカンダリストレージ媒体をPalmハンドヘルドに接続する方法に起因して、アプリケーションは拡張カード上で直接実行することはできませんし、データベースもまずメインメモリに転送して初めてデータマネージャで操作することができます。しかし、VFSマネージャを使用するように書かれたアプリケーションは拡張カード上のファイルを直接操作することができます。
- NOTE
- .prc ファイルとデータベースにはいつでも同じ名前をつけることができます。.prc ファイル名とデータベース名が異なるアプリケーションをカードからデバイスにコピーし、それを別のカードにさらにコピーした場合、ファイル名が変わってしまう場合があります。これはハンドヘルドからカードにアプリケーションをコピーした場合、データベース名がファイル名に使用されるためです。
スタンドアロンのアプリケーション
ユーザーに対して自己完結な ―― つまりデータベースを別途必要としない ―― アプリケーションを実行させるために必要なのは、以下の2つのうちいずれかを実行することだけです。
- カードが拡張スロットに挿入された時に常にアプリケーションを実行させたければ、単純にそのアプリケーションの名前を start.prc にして /PALM ディレクトリ配下に置きます。オペレーティングシステムはこのアプリケーションをメインメモリに転送し、自動的に実行してくれます。
- アプリケーションを必要に応じて実行する場合、それを /PALM/Launcher ディレクトリに配置します。このディレクトリに置かれているアプリケーションは全て、ユーザーが拡張カードの名前のカテゴリを選択した時にランチャに表示されます。
これらの仕組みはいずれも、VFSマネージャや拡張マネージャのAPIを知らないアプリケーションをカードから実行できるようにします。実行に先立ってメインメモリに転送されるため、これらのアプリケーションは自身が拡張カードから実行されていることを知る必要がありません。これらのアプリケーションが作成するデータベースは通常ストレージヒープ上に配置されます。アプリケーションを格納しているカードが取り外されると、アプリケーションは実行中でない限りメインメモリから削除されます。そうでない場合は、アプリケーションが実行中でなくなるまでメモリに留まります。アプリケーションが作成したデータベースベースは全て残留します。カードが再び挿入されてアプリケーションが再実行されると、アプリケーションは再度メインメモリにコピーされてそれらのデータベースにアクセスできます。
静的データを伴うアプリケーション
多くのアプリケーションは、インストール時から1つ以上の関連するデータベースが付属しています。これらのアプリケーションは、自身が拡張カードに格納されていることを少なくともある程度は認識している必要があります。
アプリケーションのデータを Palm のデータベースフォーマットで保存する具体的な理由がないのであれば、VFS マネージャの豊富な I/O 操作を使ってカード上のデータを読み書きしたいと考えるかもしれません。拡張メディアのデータストレージはハンドヘルドのメモリに比べて大容量なので、データストレージ容量の大きさが重要になるアプリケーションでは後者の方法が好まれます。
付属のデータベース
ランチャの使用によってアプリケーションがカードから起動された場合、/PALM/Launcher ディレクトリ配下にある付属のデータベースもインポートされます。付属のデータベースはそれを“所有する”アプリケーションと同じクリエータを持ち、dmHdrAttrBundle ビットがセットされています。付属のデータベースはゲームのレベルデータベースのような読取り専用データを意図していることに注意して下さい。付属のデータベースはユーザーが他のアプリケーションに切り替えた時点でアプリケーションとともにメインメモリから削除され、拡張カードにコピーし返されることはありません。
拡張カードとのPalmデータベースの転送
VFSExportDatabaseToFile 関数は、データベースをハンドヘルドの内部フォーマットから同等の .prc または .pdb ファイルに変換し、拡張カードに転送します。VFSImportDatabaseFromFile 関数はその逆を行ないます。つまり、.prc または .pdb ファイルをメインメモリに転送し、Palm OS が使用する内部フォーマットに変換します。これらの関数は、Palm データベースをメインメモリと拡張カードの間で移動させる時に使用して下さい。これら2つの関数はデータの変換と転送のためにエクスチェンジマネージャ関数に依存しています。エクスチェンジマネージャを使用したデータの送受信の詳細については、「Palm OS Programmer's Companion, vol. II, Communications」の“1 オブジェクト交換”を参照して下さい。
VFSExportDatabaseToFile 関数と VFSImportDatabaseFromFile 関数はアトミックで、データベースのサイズと転送方式に依存して時間がかかります。プログレスダイアログを表示したりユーザーのキャンセル操作を許可したい場合には、かわりにVFSExportDatabaseToFileCustom 関数と VFSImportDatabaseFromFileCustom 関数を使用して下さい。これらの関数はアプリケーションが指定したコールバック関数を繰り返し呼び出します。このコールバック関数の内部で進行状況の表示を更新できます。このコールバック関数からの復帰値によって、データベース転送を続行すべきかどうかを指定できます。続行すべきであれば errNone を返却し、中断する場合はそれ以外の値を返却します。コールバック関数の詳細については、Palm OS Programmer's API Reference の VFSExportProcPtr と VFSImportProcPtr の説明を参照して下さい。
以下のコードは、VFSImportDatabaseFromFileCustom 関数を進捗状況表示付きで使用する方法を示しています。
リスト 7.3 VFSImportDatabaseFromFileCustom 関数の使用
typedef struct { ProgressType *progressP; const Char *nameP; } CBDataType, *CBDataPtr; static Boolean ProgressTextCB(PrgCallbackDataPtr cbP) { const Char *nameP = ((CBDataPtr) cbP->userDataP)->nameP; // Set up the progress text to be displayed StrPrintF(cbP->textP, "Importing %s.", nameP); cbP->textChanged = true; return true; // So what we specify here is used to update the dialog } static Err CopyProgressCB(UInt32 size, UInt32 offset, void *userDataP) { CBDataPtr CBDataP = (CBDataPtr) userDataP; if (offset == 0) { // If we're just starting, we need to set up the dialog CBDataP->progressP = PrgStartDialog("Importing Database", ProgressTextCB, CBDataP); if (!CBDataP->progressP) return memErrNotEnoughSpace; } else { EventType event; Boolean handled; do { EvtGetEvent(&event, 0); // Check for events handled = PrgHandleEvent(CBDataP->progressP, &event); if (!handled) { // Did the user tap the "Cancel" button? if( PrgUserCancel(CBDataP->progressP) ) return exgErrUserCancel; } } while(event.eType != sysEventNilEvent); } return errNone; } static Err ImportFile(UInt16 volRefNum, Char *pathP, Char *nameP, UInt16 *cardNoP, LocalID *dbIDP) { CBDataType userData; Char fullPathP[256]; Err err; userData.progressP = NULL; userData.nameP = nameP; StrPrintF(fullPathP, "%s/%s", pathP, nameP); // rebuild full path to the file err = VFSImportDatabaseFromFileCustom(volRefNum, fullPathP, cardNoP, dbIDP, CopyProgressCB, &userData); if (userData.progressP) // If the progress dialog was displayed, remove it. PrgStopDialog(userData.progressP, (err == exgErrUserCancel) ); return err; }
拡張カード上のPalmデータベースの検索
VFSマネージャには、拡張カード上に配置されたPalmデータベースの内容を検索するために特別にデザインされた関数があります。ただし、このアクセスは読み取り専用です。カード上のデータベースからレコードやリソースを個別に抽出したり、最終更新日付などの情報を取得することができます。しかし、それに対応する、カード上のデータベースに対してレコードやリソースを更新したり特定の情報を設定したりする関数は存在しません。そのようなことをする場合にはデータベースをメインメモリにインポートし、必要な変更を行なってからカードにエクスポートする必要があります。
メインメモリにインポートすることなく、拡張カード上のデータベースからレコードを取得するには、VFSFileDBGetRecord 関数を使用します。この関数は DmGetRecord に似ていますが、メインメモリ上のデータベースではなく外部メディア上のファイルに対して機能します。この関数は適切なサイズのハンドルをアロケートしてから指定のレコードをストレージヒープに転送します。このメモリ領域は、不要になり次第アプリケーションが MemHandleFree を使用して開放しなければならないことに注意して下さい。
VFSFileDBGetResource 関数は似たような処理を行ないますが、データベースのレコードをロードするかわりに、拡張カード上のリソースデータベースから指定されたリソースをロードします。ロードされたリソースはストレージヒープに格納されます。これについても、不要になったらメモリを開放しなければなりません。
外部メディア上のデータベースからより一般的な情報を取得するには、VFSFileDBInfo を使用します。VFSFileGetAttributes と VFSFileGetDate を使って拡張カード上のファイルから取得できる情報に加え、VFSFileDBInfo は以下の情報を返します。
- データベース名
- データベースのバージョン
- データベースが変更された回数
- アプリケーション情報ブロックのハンドル
- ソート情報ブロックのハンドル
- データベースのタイプ
- データベースのクリエータ
- データベースのレコード数
- NOTE
- このセクションで説明している関数には、データベースファイルのフォーマットを解析するための大きなオーバーヘッドがあります。これらの関数を頻繁に使用することはお勧めしません。また、アプリケーション情報ブロックまたはソート情報ブロックを要求した場合は、不要になり次第ハンドルを開放して下さい。