今回は、ファイルのオープン(Open)とクローズ(Close)ファイルへのデータ書き込み(Write)とファイルからの読み込み(Read)、ファイルの削除(Delete)やファイル名の変更(Rename)など、一般的なファイル処理を調べてみます。
最初はファイルのオープンです。Mac OS X 10.4になり、今までCarbon Frameworkで親しまれてきたFSpOpenDF()やFSpOpenRF()など、引数にFSSpec構造体を渡すAPIは、そのほとんどがDEPRECATED指定となりました。ヘッダーファイルFiles.hに記載されているコメントでも言及されていますが、現在は代わりにFSOpenFork()を利用します。

まずオープンしたいファイルをFSRefで指定します。次に対象となるフォーク名をユニコード文字列で指定します。Macintoshのファイルシステムでは、ファイル内部にデータフォークとリソースフォークの2つのデータ領域を持つことが可能です。この仕組みは、Mac OS Xでも存続しています(消える言う噂もありましたが...)。通常のファイル処理ではデータフォークの方をオープンすることがほとんです。その場合には、ディフォルト値としてforkNameLengthにゼロを、forkNameにはNULLを渡せばOKです。もし、リソースフォークの方をオープンしたければ、FSGetResourceForkName()で得た名称をユニコード文字列として渡します。同様に、データフォーク名を得るためのFSGetDataForkName()というAPIも存在しています。
OSErr FSGetResourceForkName( HFSUniStr255 * resourceForkName );
OSErr FSGetDataForkName( HFSUniStr255 * dataForkName );
次のファイルパーミッション(アクセス権)については、以下の7種類から選択することが可能です。データの読み書きをする一般的なファイル処理では、fsRdWrPermを選択しておけば良いでしょう。ファイルオープンが成功すると、forkRefNumにはそのファイル固有のリファレンス番号が返されます。その後、このリファレンス番号を用いてファイルデータの読み書きを行うことになります。

実際の作業では、ファイルをFSRefで指定するのではなく、ファイル名やパス名などで指定したい場合も多々あります。例えば、親ディレクトリ(フォルダ)のFSRefとファイル名(CFStringRef)を引数で渡すことで、対象ファイルをオープンするopenNameFile()ルーチンを作成すると以下のようになります。

ファイルからのデータの読み込みには、以下のFSReadFork()を利用します。

読み込みデータ位置の意味は以下の4種類から選択することが可能です。また、読み込みポジションはSInt64(64ビット整数)で指定できますが、一度に読み込むデータ量はByteCount(32ビット整数)指定となり4G Byteに制限されています。

ファイルからのデータの書き込みには、以下のFSWriteFork()を利用します。引数の内容は、FSReadFork()とほとんど同じです。

アクセスが終了したファイルを閉じるのには、以下のFSCloseFork()にファイルリファレンス番号を渡たします。
OSErr FSCloseFork( SInt16 forkRefNum );
またファイルやフォルダ(ディレクトリ)の削除は、FSDeleteObject()で行えます。対象がフォルダの場合には、その中にファイルや別フォルダが含まれたままだと削除ができませんので注意してください。
OSErr FSDeleteObject( const FSRef *ref );
最後に紹介するのは、ファイルやフォルダ名を変更するためのFSRenameUnicode()です。引数のtextEncodingHintにkTextEncodingUnknownを代入しておけば、ファイルシステムがディフォルトテキストエンコーディングを利用してくれます。

ところで先ほどリソースフォークの話題が出ましたので、ついでにリソースファイルに関する注意点をいくつか上げておきます。もし、GetResource()やGetIndResource()などでリソースファイル内部の個々のリソースデータ(PICTリソースなど)にアクセスしたい場合には、リソースファイルをオープンしてカレントリソースに設定しておく必要があります。つまり、単純にFSOpenFork()で対象ファイルのリソースフォークをオープンするだけではマズイということです。
昔からこの働きをしていたのは、Resources.hに定義されているFSpOpenResFile()でした。これは、引数にFSSpec構造体を渡しファイル指定する旧型APIですが、何か事情があるのか、まだDEPRECATED指定になっていません(不思議?)。問題は、このAPIを用いてもリソースフォークに保存されているリソースデータにしかアクセスできないことです。Mac OS Xから、アプリケーションバンドルのResourcesフォルダに保存されるリソースファイルなどは、データフォークにそのデータが保存されています(ややこしい)。よって、それらにアクセスするためには、FSpOpenResFile()の代わりにFSOpenResourceFile()を使う必要があるわけです。

先ほど取り上げたFSOpenFork()と同様に、forkNameLengthにゼロを、forkNameにNULLを渡した時にディフォルト対象はデータフォークとなります。ディフォルトはリソースフォークではないので注意してください。こうしてオープンしたファイルをクローズするには、FSCloseFork()ではなくCloseResFile()を使いますので、こちらも注意が必要です。
次回は、色々なファイル処理の話題を集めてみたいと思います。ディレクトリ・カタログからファイルを抽出するような処理にもチャレンジしてみます。