FSSpec vs. FSRef Part 1

前文

まずは Files.h を一通り読んでみよう。そこにはたくさんの記述があって、新しい API だって全部載っている。存在すら知らない API は使うことだってできやしないのだから。読むのにはちょっとばかり時間がかかるけど、価値あるものになることでしょう。

Q&A

FSSpec と FSRef はどう違う?

最も大きな違いは、FSRef は存在しないファイルを指すことができないことですね。それと FSRef は 80バイトの領域ということがわかっているだけで、中身の構造については Apple は明らかにしていないという点。さらに、FSRef は内部にファイル名を保持していないという点。Mac OS X はファイル名に最大 255文字の UniChar を使えるんだから当たり前だけど。(Part 3 で詳述)

それと、CarbonLib を使ったプロジェクトの場合には、FSRef が HFS+ API として MacOS 9 で新たに追加されたということに注意。CarbonLib は FSRef 関連のラッパを用意しているけど、中身は実装されていないから、実際には OS 8 で FSRef を使った CarbonLib API を使えないのです。

それぞれの相互変換はどうしたらいい?

FSSpec → FSRef なら FSpMakeFSRef()。FSRef → FSSpec なら FSGetCatalogInfo() を使います。

2つの FSRef が同じものを指しているかどうかを調べるには?

FSCompareFSRefs() を使います。

FSRef からアイテム名をとるにはどうしたらいい?

FSGetCatalogInfo() で HFSUniStr255 が取得できます。HFSUniStr255 は 512バイトの領域を消費するので、CFStringRef に格納するようにした方が良いでしょう。これには、メモリ領域の節約という意味もあるけれど、Core Foundation は CFString を操作する有益な API をいろいろと提供しているという理由も大きいです。(ついでに言うと、CFStringRef のラッパークラスを用意するのがいいと思う) FSGetCatalogInfo() はファイルシステム名を返すから、もし Finder が表示しているような表示名が欲しい場合は LSCopyDisplayNameForRef() を使うといいです。(LaunchServices.h を参照のこと)

FSGetCatalogInfo() を使うと、親フォルダも取得することができます。

存在しないアイテムを表現するにはどうしたらいい? (例えばこれから作ろうとしているファイルとか)

Apple は CFURLRef を推奨しているけど、私の経験では Mac OS 9 で問題が生じることがある。なので、その代わりに私はそのアイテムの親フォルダ FSRef と、アイテム名を HFSUniStr255 で保持したクラスを使ってます。

class CExtFSRef {
    public:// No lectures on why these should be private. ;-)
        FSRef parentFSRef;
        THFSUniStr255 name;
...
// Some useful member functions.
};

THFSUniStr255 というのは HFSUniStr255 をラップした自作クラスです。CExtFSRef クラスは NavCreatePutFileDialog() の結果で得られたものを保持するのに使っています。Unicode-savvy なファイル生成 API は、親 FSRef と HFSUniStr255 を引数にするので、CFURLRef にして保持せずに、そのままそれを保持しているわけです。もちろん、ファイル名を CFStringRef で保持しておいて、必要に応じて HFSUniStr255 に変換して使う、という方法でもいいでしょう。


訳文に対してのフィードバックは amn@mugiwara.jp まで

[index] [Part 1] [Part 2] [Part 3]