● ToolBox API徒然草(2007/07/23)

  このニュースは、MOSAの会員にのみ配布されているデベロッパー向けの
  デジタルマガジンMOSADeNのに掲載された記事です。ほぼ一ヶ月遅れで
  ここに掲載されて行きます

 〜 Carbonモダンアプリケーションへの道(その17) 〜


今回は、ファイル処理の色々な話題を集めてみました。ファイルパス名の扱い、エイリアス処理、ディレクトリ・カタログからファイルを抽出する処理などです。

今まではファイル保存場所を特定するためにFSRefを用いましたが、Mac OS Xになってからは、そのUNIX遺伝子の影響でファイルパス名(POSIX Path)が使われることが多々あります。例えば、環境設定にユーザの好みのファイル保存場所(フォルダ)を記録させておきたい場合には、ファイル選択ダイアログ(Navigation Service)でフォルダを選択させ、得られたFSRefをパス名に変換してからテキストとして保存します。Navigation Serviceで得たFSRefをパス名に変換するには、次のFSRefMakePath()を利用します。

OSStatus FSRefMakePath(const FSRef *ref, UInt8 *path, UInt32 maxPathSize);

maxPathSizeにはパス名用のバッファ最大サイズを設定しますが、まあ1000もあれば問題ないでしょう。返ってきたPOSIX PathはUTF8でエンコーディングされていますので注意してください。逆にパス名からFSRefを得るにはFSPathMakeRef()を用います。APIから返されるisDirectoryは、そのパス名がファイルなのかディレクトリ(フォルダ)なのかを示します。ディレクトリの場合には、isDirectoryにtrueが代入されるわけです。

OSStatus FSPathMakeRef(const UInt8 *path, FSRef *ref, Boolean *isDirectory);

ちなみに、ファイル保存場所を指定するもうひとつの方法は、CoreFoundationに定義されているCFURLRefを使うことです。しかし、CFURLRefはFileマネージャではほとんど用いられていません。ボリュームパスをCFURLRefで返すFSCopyURLForVolume()を含めて、定義されているAPIは4つのみです。CFURLRefの利用方法や詳細については、ヘッダファイルのCFURL.hを参照してみてください。

ところで、環境設定にフォルダのパス名を保存しておいても、ユーザがフォルダ名を変更してしまうと、そのパス名が無効になってしまう場合があります。これは、保存場所をパス名で管理している時の大きなデメリットです。こうした事故を防ぐために、Macintoshのファイルシステムには、もうひとつ便利なファイル保存場所管理の仕組みが存在しています。それがAliasマネージャです。

Aliasマネージャを用いると、一度記録されたボリューム、フォルダ、ファイルを、あらゆる手段を用いて探し出してくれます(ファイル名を変更したりしても大丈夫)。また、対象がネットワークボリューム内であれば、それをマウントする処理までも受け持ってくれます。Aliasは大変便利な仕組みでしたので、Mac OS 9時代には多種多様な処理に利用されていました。筆者も、画像データベースで保存したファイルの管理としてAliasを重宝していました。しかし、何故だかMac OS Xでは積極的に活用されていません。Cocoaには同様なメソッドが存在しないという話も聞きます(Handleを使うのが問題なのか?)。

Alias関連のAPIが定義されているヘッダファイルは、Files.hではなくAliases.hですので注意してください。Fileマネージャと同様に、FSSpecを引数として渡していたNewAlias()やResolveAlias()などは、すべてがDEPRECATED指定となっています。現在ではFSSpecの代わりにFSRefを引数として渡すSFNewAlias()やFSResolveAlias()を利用します。

OSErr FSNewAlias( FSRef *fromFile,FSRef *target, AliasHandle *inAlias );

OSErr FSResolveAlias( FSRef *fromFile, AliasHandle alias,FSRef *target,Boolean *wasChanged );

Aliasの仕組みは簡単です。FSNewAlias()にファイル保存場所のFSRefを渡すと、ファイルに関するより詳細な情報が含まれたAliasHandleが返されます。これを保存しておいて必要な時にFSResolveAlias()に渡せば、望んだファイルのFSRefが得られる訳です。両APIに引数として渡しているfromFile(FSRef)は、ファイルを特定場所からの相対検索で見つけ出すための基点です。これにNULLを代入した場合には、絶対位置による検索が実行されます。通常の場合はNULLを代入しておけば問題ありません。

また、Finderではフォルダやファイルのエイリアスを作成することが可能です。状況によっては、自作アプリケーションにドラッグ&ドロップされたファイルが、通常ファイルなのかエイリアスなのかを判断する必要が出てきます。Aliasマネージャには、そうした判断のためにFSIsAliasFile()が用意されています。もしそのファイルがエイリアスファイルであればFSResolveAliasFile()を使い、ファイル本体(本物)のFSRefを得ることも可能です。

OSErr FSIsAliasFile( FSRef *fileRef,Boolean *aliasFileFlag,Boolean *folderFlag);

OSErr FSResolveAliasFile( FSRef *theRef,Boolean resolveAliasChains, Boolean *targetIsFolder,Boolean *wasAliased );

続いてディレクトリ・カタログからJPEGファイルだけを抽出するような場合の話です。今まで、こうした処理についてはPBGetCatInfo()にFSSpecを渡すことで実現していました。しかし、すでにBGetCatInfo()もDEPRECATED指定となっています。



新しい方法は、FSOpenIterator()でFSIteratorを作成し、それをFSGetCatalogInfoBulk()に渡すことで実現します。FSGetCatalogInfoBulk()はBGetCatInfo()と異なり、カタログ検索の階層レベルも指示できます。これにより、フォルダ内のフォルダ内といった具合に検索の階層レベルを掘り進めて行くことも可能となりました。



今回でCarbonのファイルシステムに関する話は終了したいと思います。さて次回からはWWDC2007の流れを考慮し(笑)開発に利用するFrameworkをCarbonからCocoaへ切り替える作業を順次解説して行きたい考えています。ご期待ください!


copyright 2007 Ottimo, Inc. All rights reserved
無断転載・引用禁止