ファイルを操作してみよう - 2 / 3 -
空ではないディレクトリを削除する方法
次に上記コードを改造して、指定されたディレクトリが空でなくても削除を行う関数を作成してみましょう。
static void RmDirRecursive(FilesystemApplet* app,const char* name) { IShell* shell = app->a.m_pIShell; IFileMgr* filemgr; FileInfo info; // IFileMgr インタフェースの作成 ISHELL_CreateInstance(shell,AEECLSID_FILEMGR,(void*)&filemgr); // 列挙をディレクトリ用に初期化 IFILEMGR_EnumInit(filemgr,name,TRUE); // 次の要素を取得 while (IFILEMGR_EnumNext(filemgr,&info)) { // ディレクトリの中を再帰的に巡回 RmDirRecursive(app,info.szName); } // 列挙をファイル用に初期化 IFILEMGR_EnumInit(filemgr,name,FALSE); // 次の要素を取得 while (IFILEMGR_EnumNext(filemgr,&info)) { // ファイルの削除 IFILEMGR_Remove(filemgr,info.szName); } // ディレクトリの削除 IFILEMGR_RmDir(filemgr,name); // IFileMgr インタフェースの破棄 IFILEMGR_Release(filemgr); return; } // 呼び出し RmDirRecursive(app,"target_dir");
上記コードの RmDirRecursive 関数を使用すると、空でないディレクトリも削除することができます。上記コードでは "target_dir" ディレクトリを削除しています。もしも間違えて "" と指定して呼び出したら大変です。アプリの実体と同じディレクトリ内の全てのファイル(削除可能なものだけ)が削除されてしまいます。実験するときは注意しましょう。
※上記コードをエミュレータ上で動作させる場合、 "target_dir" ディレクトリを Windows のエクスプローラなどで開いていると正常に削除できない場合があります。
ファイルを操作してみる
ここまではディレクトリの操作の方法を解説してきました。それでは次に、 IFile インタフェースを使用したファイルの操作の方法について解説します。
IFile インタフェースには以下のような API が存在します。ファイルの操作は、これらの API を使用して行います。
関数名 | 解説 |
---|---|
IFILE_GetInfo | ファイルの情報を取得します。 |
IFILE_GetInfoEx | ファイルの拡張情報を取得します。 |
IFILE_Read | ファイルからデータを読み込みます。 |
IFILE_Readable | ファイルが読み込み可能になるまで読み込みをペンディングします。 |
IFILE_Write | ファイルへデータを書き出します。 |
IFILE_Cancel | IFILE_Readable 関数によって登録されたコールバックをキャンセルします。 |
IFILE_Seek | ファイルのアクセス位置を変更します。 |
IFILE_Truncate | ファイルを切り詰めます。 |
IFILE_SetCacheSize | IFile インタフェースの内部バッファリング用のキャッシュサイズを設定します。 |
※上記表は、頻繁に使用されるAPIしか列挙していません。より、詳しい情報は BREW API リファレンスを参照してください。
ファイルのオープンとクローズ
BREW でファイルの内容を読み書きするためにファイルをオープンするには、 IFileMgr インタフェースの IFILEMGR_OpenFile 関数を使用します。また、オープンされたファイルをクローズするには、 IFile インタフェースの IFILE_Release 関数を使用します。 IFILEMGR_Close 関数や IFILE_Close 関数などは存在しません。では、以下に新しいファイル作成した後、オープンしてクローズするコードを示します。
IShell* shell = app->a.m_pIShell; IFileMgr* filemgr; IFile* file; // IFileMgr インタフェースの作成 ISHELL_CreateInstance(shell,AEECLSID_FILEMGR,(void*)&filemgr); // ファイルの新規オープン file = IFILEMGR_OpenFile(filemgr,"sample.txt",_OFM_CREATE); // ファイルのクローズ IFILE_Release(file); // IFileMgr インタフェースの破棄 IFILEMGR_Release(filemgr);
※上記コードは "sample.txt" という名前のファイルが既に存在する場合は正常にファイルをオープンすることができません。詳細は以下のオープンモードの表を参照してください。
ここで IFILEMGR_OpenFile 関数の第 3 引数はファイルをオープンするときのモードを表します。 BREW で使用できるオープンモードには以下のようなものがあります。
モード | 解説 |
---|---|
_OFM_READ | ファイルを読み込みモードでオープンする。ファイルが存在しない場合は作成しない。 |
_OFM_READWRITE | ファイルを読み込み / 書き込みモードでオープンする。ファイルが存在しない場合は作成しない。 |
_OFM_APPEND | ファイルを読み込み / 書き込みモードでオープンするが、あらかじめアクセス位置をファイルの末尾に移動させる。ファイルが存在しない場合は作成しない。 |
_OFM_CREATE | ファイルを読み込み / 書き込みモードで作成する。既にファイルが存在する場合はファイルがオープンされることはなく、エラーとなる。 |
では、ファイルが存在しないときはファイルを作成してオープンし、ファイルが存在するときはファイルをオープンできるように、コードを改良してみましょう。
IShell* shell = app->a.m_pIShell; IFileMgr* filemgr; IFile* file; // IFileMgr インタフェースの作成 ISHELL_CreateInstance(shell,AEECLSID_FILEMGR,(void*)&filemgr); // ファイルのオープン file = IFILEMGR_OpenFile(filemgr,"sample.txt",_OFM_READWRITE); // ファイルが存在しなかった場合 if (file == NULL) { // ファイルの新規オープン file = IFILEMGR_OpenFile(filemgr,"sample.txt",_OFM_CREATE); } // ファイルのクローズ IFILE_Release(file); // IFileMgr インタフェースの破棄 IFILEMGR_Release(filemgr);
まず、ファイルを読み書きモードでオープンし、失敗した場合、作成モードでオープンを試みるように修正しました。より、安全なファイル処理を行いたい場合は、 IFILEMGR_GetLastError 関数を使用して具体的なエラー内容に応じて処理を変更します。
ファイルの情報を取得してみる
BREW にはディレクトリやファイルの情報を取得するための API があります。それらの API は FileInfo 構造体や AEEFileInfoEx 構造体に情報を詰め込んで結果を返してくれます。 FileInfo 構造体はファイルの属性やファイルが作成された日時、ファイルサイズ、ファイル名などが格納されています。また、 AEEFileInfoEx 構造体はそれらの情報に加えて、ファイルの説明やファイルの所有者などの情報が格納されています。普通 FileInfo 構造体を使用する事が多いと思いますので、ここでは FileInfo 構造体を使用したコードを示します。
IShell* shell = app->a.m_pIShell; IFileMgr* filemgr; IFile* file; FileInfo info; // IFileMgr インターフェースの作成 ISHELL_CreateInstance(shell,AEECLSID_FILEMGR,(void*)&filemgr); // ファイルのオープン file = IFILEMGR_OpenFile(filemgr,"sample.txt",_OFM_READ); // ファイル情報の取得 IFILE_GetInfo(file,&info); // ファイル情報の出力 DBGPRINTF("name : %s, size : %06d bytes",info.szName,info.dwSize); // ファイルのクローズ IFILE_Release(file); // IFileMgr インターフェースの破棄 IFILEMGR_Release(filemgr);
いちいちファイルをオープンしなくても情報を取得することができます。
IShell* shell = app->a.m_pIShell; IFileMgr* filemgr; FileInfo info; // IFileMgr インターフェースの作成 ISHELL_CreateInstance(shell,AEECLSID_FILEMGR,(void*)&filemgr); // ファイル情報の取得 IFILEMGR_GetInfo(filemgr,"sample.txt",&info); // ファイル情報の出力 DBGPRINTF("name : %s, size : %06d bytes",info.szName,info.dwSize); // IFileMgr インターフェースの破棄 IFILEMGR_Release(filemgr);